2e719d6de7ae14312ae3e8531a2ba26817c66778
[krb5.git] / src / clients / kpasswd / kpasswd.c
1 #include <stdio.h>
2 #include <sys/types.h>
3
4 #ifndef _WIN32
5 #include <unistd.h>
6 #endif
7
8 #include <krb5.h>
9
10 #define P1 "Enter new password: "
11 #define P2 "Enter it again: "
12
13 #ifdef HAVE_PWD_H
14 #include <pwd.h>
15
16 void get_name_from_passwd_file(program_name, kcontext, me)
17     char * program_name;
18     krb5_context kcontext;
19     krb5_principal * me;
20 {
21     struct passwd *pw;
22     krb5_error_code code;
23     if (pw = getpwuid((int) getuid())) {
24         if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) {
25             com_err (program_name, code, "when parsing name %s", pw->pw_name);
26             exit(1);
27         }
28     } else {
29         fprintf(stderr, "Unable to identify user from password file\n");
30         exit(1);
31     }
32 }
33 #else /* HAVE_PWD_H */
34 void get_name_from_passwd_file(kcontext, me)
35     krb5_context kcontext;
36     krb5_principal * me;
37 {
38     fprintf(stderr, "Unable to identify user\n");
39     exit(1);
40 }
41 #endif /* HAVE_PWD_H */
42
43 int main(int argc, char *argv[])
44 {
45    krb5_error_code ret;
46    krb5_context context;
47    krb5_principal princ;
48    char *pname;
49    krb5_ccache ccache;
50    krb5_get_init_creds_opt opts;
51    krb5_creds creds;
52
53    krb5_timestamp now;
54    krb5_data ap_req;
55    krb5_auth_context auth_context;
56    char pw[1024];
57    int pwlen;
58    krb5_data chpw_req, chpw_rep;
59    int result_code;
60    krb5_data result_code_string, result_string;
61
62    if (argc > 2) {
63       fprintf(stderr, "usage: %s [principal]\n", argv[0]);
64       exit(1);
65    }
66
67    pname = argv[1];
68
69    if (ret = krb5_init_context(&context)) {
70       com_err(argv[0], ret, "initializing kerberos library");
71       exit(1);
72    }
73
74 #if 0
75    krb5_init_ets(context);
76 #endif
77
78    /* in order, use the first of:
79       - a name specified on the command line
80       - the principal name from an existing ccache
81       - the name corresponding to the ruid of the process
82
83       otherwise, it's an error.
84       */
85
86    if (pname) {
87       if (ret = krb5_parse_name(context, pname, &princ)) {
88          com_err(argv[0], ret, "parsing client name");
89          exit(1);
90       }
91    } else if ((ret = krb5_cc_default(context, &ccache)) != KRB5_CC_NOTFOUND) {
92       if (ret) {
93          com_err(argv[0], ret, "opening default ccache");
94          exit(1);
95       }
96
97       if (ret = krb5_cc_get_principal(context, ccache, &princ)) {
98          com_err(argv[0], ret, "getting principal from ccache");
99          exit(1);
100       }
101
102       if (ret = krb5_cc_close(context, ccache)) {
103          com_err(argv[0], ret, "closing ccache");
104          exit(1);
105       }
106    } else {
107        get_name_from_passwd_file(argv[0], context, &princ);
108    }
109
110    krb5_get_init_creds_opt_init(&opts);
111    krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
112    krb5_get_init_creds_opt_set_renew_life(&opts, 0);
113    krb5_get_init_creds_opt_set_forwardable(&opts, 0);
114    krb5_get_init_creds_opt_set_proxiable(&opts, 0);
115
116    if (ret = krb5_get_init_creds_password(context, &creds, princ, NULL,
117                                           krb5_prompter_posix, NULL, 
118                                           0, "kadmin/changepw", &opts)) {
119       if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
120          com_err(argv[0], 0,
121                  "Password incorrect while getting initial ticket");
122       else
123          com_err(argv[0], ret, "getting initial ticket");
124       exit(1);
125    }
126
127    pwlen = sizeof(pw);
128    if (ret = krb5_read_password(context, P1, P2, pw, &pwlen)) {
129       com_err(argv[0], ret, "while reading password");
130       exit(1);
131    }
132
133    if (ret = krb5_change_password(context, &creds, pw,
134                                   &result_code, &result_code_string,
135                                   &result_string)) {
136       com_err(argv[0], ret, "changing password");
137       exit(1);
138    }
139
140    if (result_code) {
141       printf("%.*s%s%.*s\n",
142              result_code_string.length, result_code_string.data,
143              result_string.length?": ":"",
144              result_string.length, result_string.data);
145       exit(2);
146    }
147
148    free(result_string.data);
149    free(result_code_string.data);
150
151    printf("Password changed.\n");
152    exit(0);
153 }