summaryrefslogtreecommitdiffstats
path: root/src/clients/kpasswd/kpasswd.c
blob: da66102daf7aa6d65f9e21fbff6ed4ba0626e7cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <stdio.h>
#include <sys/types.h>

#ifndef _WIN32
#include <unistd.h>
#endif

#include <krb5.h>

#define P1 "Enter new password: "
#define P2 "Enter it again: "

#ifdef HAVE_PWD_H
#include <pwd.h>

static
void get_name_from_passwd_file(program_name, kcontext, me)
    char * program_name;
    krb5_context kcontext;
    krb5_principal * me;
{
    struct passwd *pw;
    krb5_error_code code;
    if ((pw = getpwuid((int) getuid()))) {
	if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) {
	    com_err (program_name, code, "when parsing name %s", pw->pw_name);
	    exit(1);
	}
    } else {
	fprintf(stderr, "Unable to identify user from password file\n");
	exit(1);
    }
}
#else /* HAVE_PWD_H */
void get_name_from_passwd_file(kcontext, me)
    krb5_context kcontext;
    krb5_principal * me;
{
    fprintf(stderr, "Unable to identify user\n");
    exit(1);
}
#endif /* HAVE_PWD_H */

int main(int argc, char *argv[])
{
   krb5_error_code ret;
   krb5_context context;
   krb5_principal princ;
   char *pname;
   krb5_ccache ccache;
   krb5_get_init_creds_opt opts;
   krb5_creds creds;

   char pw[1024];
   unsigned int pwlen;
   int result_code;
   krb5_data result_code_string, result_string;

   if (argc > 2) {
      fprintf(stderr, "usage: %s [principal]\n", argv[0]);
      exit(1);
   }

   pname = argv[1];

   ret = krb5_init_context(&context);
   if (ret) {
      com_err(argv[0], ret, "initializing kerberos library");
      exit(1);
   }

   /* in order, use the first of:
      - a name specified on the command line
      - the principal name from an existing ccache
      - the name corresponding to the ruid of the process

      otherwise, it's an error.
      */

   if (pname) {
      if ((ret = krb5_parse_name(context, pname, &princ))) {
	 com_err(argv[0], ret, "parsing client name");
	 exit(1);
      }
   } else if ((ret = krb5_cc_default(context, &ccache)) != KRB5_CC_NOTFOUND) {
      if (ret) {
	 com_err(argv[0], ret, "opening default ccache");
	 exit(1);
      }

      if ((ret = krb5_cc_get_principal(context, ccache, &princ))) {
	 com_err(argv[0], ret, "getting principal from ccache");
	 exit(1);
      }

      if ((ret = krb5_cc_close(context, ccache))) {
	 com_err(argv[0], ret, "closing ccache");
	 exit(1);
      }
   } else {
       get_name_from_passwd_file(argv[0], context, &princ);
   }

   krb5_get_init_creds_opt_init(&opts);
   krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
   krb5_get_init_creds_opt_set_renew_life(&opts, 0);
   krb5_get_init_creds_opt_set_forwardable(&opts, 0);
   krb5_get_init_creds_opt_set_proxiable(&opts, 0);

   if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL,
					   krb5_prompter_posix, NULL, 
					   0, "kadmin/changepw", &opts))) {
      if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
	 com_err(argv[0], 0,
		 "Password incorrect while getting initial ticket");
      else
	 com_err(argv[0], ret, "getting initial ticket");
      exit(1);
   }

   pwlen = sizeof(pw);
   if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) {
      com_err(argv[0], ret, "while reading password");
      exit(1);
   }

   if ((ret = krb5_change_password(context, &creds, pw,
				   &result_code, &result_code_string,
				   &result_string))) {
      com_err(argv[0], ret, "changing password");
      exit(1);
   }

   if (result_code) {
      printf("%.*s%s%.*s\n",
	     (int) result_code_string.length, result_code_string.data,
	     result_string.length?": ":"",
	     (int) result_string.length, result_string.data);
      exit(2);
   }

   if (result_string.data != NULL) 
       free(result_string.data);
   if (result_code_string.data != NULL)
       free(result_code_string.data);

   printf("Password changed.\n");
   exit(0);
}