source: trunk/third/cns/src/kadmin/kpasswd.c @ 8789

Revision 8789, 7.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8788, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * kpasswd.c
3 *
4 * Copyright 1988 by the Massachusetts Institute of Technology.
5 *
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 *
9 * change your password with kerberos
10 */
11
12#include <mit-copyright.h>
13/*
14 * kpasswd
15 * change your password with kerberos
16 */
17
18#include <stdio.h>
19#include <string.h>
20#include <sys/types.h>
21#include <sys/param.h>
22#include <pwd.h>
23#include <kadm_err.h>
24#include "kadm.h"
25
26extern void krb_set_tkt_string();
27static int using_preauth = 0;
28
29static int oldhist[256], newhist[256];
30
31main(argc,argv)
32  int argc;
33  char *argv[];
34{
35    char name[ANAME_SZ];        /* name of user */
36    char inst[INST_SZ];         /* instance of user */
37    char realm[REALM_SZ];       /* realm of user */
38    char default_name[ANAME_SZ];
39    char default_inst[INST_SZ];
40    char default_realm[REALM_SZ];
41    int realm_given = 0;        /* True if realm was give on cmdline */
42    int use_default = 1;        /* True if we should use default name */
43    int skip_old = 0;           /* True if we should skip getting old pw */
44    struct passwd *pw;
45    int status;                 /* return code */
46    des_cblock new_key;
47    char pword[MAX_KPW_LEN];    /* storage for the password */
48    int c;
49    extern char *optarg;
50    extern int optind;
51    char tktstring[MAXPATHLEN];
52    char *ret_st;
53   
54    void get_pw_new_key();
55   
56#ifdef NOENCRYPTION
57#define read_long_pw_string placebo_read_pw_string
58#else
59#define read_long_pw_string des_read_pw_string
60#endif
61    int read_long_pw_string();
62   
63    memset(name, 0, sizeof(name));
64    memset(inst, 0, sizeof(inst));
65    memset(realm, 0, sizeof(realm));
66   
67    if (krb_get_tf_fullname(TKT_FILE, default_name, default_inst,
68                            default_realm) != KSUCCESS) {
69        pw = getpwuid((int) getuid());
70        if (pw)
71            (void) strcpy(default_name, pw->pw_name);
72        else
73            /* seems like a null name is kinda silly */
74            (void) strcpy(default_name, "");
75        strcpy(default_inst, "");
76        if (krb_get_lrealm(default_realm, 1) != KSUCCESS)
77            strcpy(default_realm, KRB_REALM);
78    }
79
80    while ((c = getopt(argc, argv, "u:n:i:r:hp")) != EOF) {
81        switch (c) {
82          case 'u':
83            if (status = kname_parse(name, inst, realm, optarg)) {
84                fprintf(stderr, "Kerberos error: %s\n",
85                        krb_get_err_text(status));
86                exit(2);
87            }
88            if (realm[0])
89                realm_given++;
90            else
91                if (krb_get_lrealm(realm, 1) != KSUCCESS)
92                    strcpy(realm, KRB_REALM);
93            break;
94          case 'n':
95            if (k_isname(optarg))
96                (void) strncpy(name, optarg, sizeof(name) - 1);
97            else {
98                fprintf(stderr, "Bad name: %s\n", optarg);
99                usage(1);
100            }
101            break;
102          case 'i':
103            if (k_isinst(optarg))
104                (void) strncpy(inst, optarg, sizeof(inst) - 1);
105            else {
106                fprintf(stderr, "Bad instance: %s\n", optarg);
107                usage(1);
108            }
109            (void) strcpy(inst, optarg);
110            break;
111          case 'r':
112            if (k_isrealm(optarg)) {
113                (void) strncpy(realm, optarg, sizeof(realm) - 1);
114                realm_given++;
115            }
116            else {
117                fprintf(stderr, "Bad realm: %s\n", optarg);
118                usage(1);
119            }
120            break;
121          case 'h':
122            usage(0);
123            break;
124          case 'p':
125            using_preauth++;
126            break;
127          default:
128            usage(1);
129            break;
130        }
131        use_default = 0;
132    }
133    if (optind < argc)
134        usage(1);
135
136    if (use_default) {
137        strcpy(name, default_name);
138        strcpy(inst, default_inst);
139        strcpy(realm, default_realm);
140    }
141    else {
142        if (!name[0])
143            strcpy(name, default_name);
144        if (!realm[0])
145            strcpy(realm, default_realm);
146    }
147
148    (void) sprintf(tktstring, "/tmp/tkt_cpw_%d",getpid());
149    krb_set_tkt_string(tktstring);
150   
151try_again:
152    get_pw_new_key(new_key, pword, name, inst, realm, realm_given, skip_old);
153    skip_old++;
154   
155    if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm))
156        != KADM_SUCCESS) {
157        com_err(argv[0], status, "while initializing");
158        memset(pword, 0, sizeof(pword));
159    } else {
160#ifdef CHECK_ONLY
161            status = kadm_check_pw(new_key, pword, (u_char **)&ret_st);
162#else
163            status = kadm_change_pw2(new_key, pword, (u_char **)&ret_st);
164#endif
165            memset(pword, 0, sizeof(pword));
166            if (ret_st) {
167                    printf("\n%s\n", ret_st);
168                    free(ret_st);
169            }
170            if (status != KADM_SUCCESS)
171                    com_err(argv[0], status,
172                            "while attempting to change password.");
173            if (status == KADM_DB_INUSE)
174                    com_err(argv[0], 0, "Please try again later.");
175            if (status == KADM_INSECURE_PW) {
176                    printf("Please choose another password.\n\n");
177                    goto try_again;
178            }
179    }
180   
181#ifdef CHECK_ONLY
182    fprintf(stderr, "Passwrd NOT changed --- this is a test version of kpasswd.\n");
183#else
184    if (status != KADM_SUCCESS)
185        fprintf(stderr,"Password NOT changed.\n");
186    else
187        printf("Password changed.\n");
188#endif
189
190    (void) dest_tkt();
191    if (status)
192        exit(2);
193    else
194        exit(0);
195}
196
197void get_pw_new_key(new_key, pword, name, inst, realm, print_realm, skip_old)
198  des_cblock new_key;
199  char *pword;
200  char *name;
201  char *inst;
202  char *realm;
203  int print_realm;              /* True if realm was give on cmdline */
204  int skip_old;
205{
206    char ppromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */
207    char npromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */
208   
209    char local_realm[REALM_SZ];
210    int status, diff, i, d;
211    char *s;
212   
213    /*
214     * We don't care about failure; this is to determine whether or
215     * not to print the realm in the prompt for a new password.
216     */
217    (void) krb_get_lrealm(local_realm, 1);
218   
219    if (strcmp(local_realm, realm))
220        print_realm++;
221   
222    if (!skip_old) {
223            (void) sprintf(ppromp,"Old password for %s%s%s%s%s:",
224                           name, *inst ? "." : "", inst,
225                           print_realm ? "@" : "", print_realm ? realm : "");
226            if (read_long_pw_string(pword, MAX_KPW_LEN-1, ppromp, 0)) {
227                    fprintf(stderr, "Error reading old password.\n");
228                    exit(1);
229            }
230
231            if (using_preauth)
232                status = krb_get_pw_in_tkt_preauth(name, inst, realm, PWSERV_NAME,
233                                                   KADM_SINST, 1, pword);
234            else
235                status = krb_get_pw_in_tkt(name, inst, realm, PWSERV_NAME,
236                                           KADM_SINST, 1, pword);
237
238            if (status != KSUCCESS) {
239                    if (status == INTK_BADPW) {
240                            printf("Incorrect old password.\n");
241                            exit(0);
242                    }
243                    else {
244                            fprintf(stderr, "Kerberos error: %s\n",
245                                    krb_get_err_text(status));
246                            exit(1);
247                    }
248            }
249            for (i = 0; i < 256; i++)
250              oldhist[i] = 0;
251            for (s = pword; *s; s++)
252              oldhist[*s & 0xff]++;
253    }
254    do {
255        (void) sprintf(npromp,"New Password for %s%s%s%s%s:",
256                       name, *inst ? "." : "", inst,
257                       print_realm ? "@" : "", print_realm ? realm : "");
258        if (read_long_pw_string(pword, MAX_KPW_LEN-1, npromp, 1))
259            go_home("Error reading new password, password unchanged.\n",0);
260        if (strlen(pword) == 0)
261            printf("Null passwords are not allowed; try again.\n");
262        for (i = 0; i < 256; i++)
263          newhist[i] = 0;
264        for (s = pword; *s; s++)
265          newhist[*s & 0xff]++;
266        for (i = 0, diff = 0; i < 256; i++) {
267          d = newhist[i] - oldhist[i];
268          if (d > 0)
269            diff += d;
270          else
271            diff -= d;
272        }
273        if (diff < 3) {
274          printf ("Password too similar to previous; try again.\n");
275          pword[0] = 0;
276        }
277    } while (strlen(pword) == 0);
278   
279#ifdef NOENCRYPTION
280    memset((char *) new_key, 0, sizeof(des_cblock));
281    new_key[0] = (unsigned char) 1;
282#else
283    (void) des_string_to_key(pword, new_key);
284#endif
285}
286
287usage(value)
288  int value;
289{
290    fprintf(stderr, "Usage: ");
291    fprintf(stderr, "kpasswd [-h ] [-n user] [-i instance] [-r realm] [-p] ");
292    fprintf(stderr, "[-u fullname]\n");
293    exit(value);
294}
295
296go_home(str,x)
297  char *str;
298  int x;
299{
300    fprintf(stderr, str, x);
301    (void) dest_tkt();
302    exit(1);
303}
304
305/* ksrvutil can fail due to talking to the wrong KDC. kpasswd will only
306   confuse the user, as the password will still get tickets, and that will
307   suffice for the change. However, the user may find it confusing if they
308   change passwords quickly and it doesn't work, so for now we have them
309   talk to the master for everything. In the long run, we would want to
310   change the protocol.
311 */
312krb_get_krbhst(h,r,n)
313    char *h;
314    char *r;
315    int n;
316{
317  return krb_get_admhst(h, r, n);
318}
Note: See TracBrowser for help on using the repository browser.