add CNS V4 library to tree for compatibility use. Installs as libkrb4.a
[krb5.git] / src / lib / krb4 / g_pw_in_tkt.c
1 /*
2  * g_pw_in_tkt.c
3  *
4  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
5  *
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include "mit-copyright.h"
11 #include "krb.h"
12 #include "prot.h"
13
14 #ifndef NULL
15 #define NULL 0
16 #endif
17
18 /*
19  * This file contains two routines: passwd_to_key() converts
20  * a password into a DES key (prompting for the password if
21  * not supplied), and krb_get_pw_in_tkt() gets an initial ticket for
22  * a user.
23  */
24
25 /*
26  * passwd_to_key(): given a password, return a DES key.
27  * There are extra arguments here which (used to be?)
28  * used by srvtab_to_key().
29  *
30  * If the "passwd" argument is not null, generate a DES
31  * key from it, using string_to_key().
32  *
33  * If the "passwd" argument is null, then on a Unix system we call
34  * des_read_password() to prompt for a password and then convert it
35  * into a DES key.  But "prompting" the user is harder in a Windows or
36  * Macintosh environment, so we rely on our caller to explicitly do
37  * that now.
38  *
39  * In either case, the resulting key is put in the "key" argument,
40  * and 0 is returned.
41  */
42 /*ARGSUSED */
43 int
44 passwd_to_key(user,instance,realm,passwd,key)
45     char *user, *instance, *realm, *passwd;
46     C_Block key;
47 {
48 #if defined(_WINDOWS) || defined(macintosh)
49     string_to_key(passwd, key);
50 #else /* unix */
51 #ifdef NOENCRYPTION
52     if (!passwd)
53         placebo_read_password(key, "Password: ", 0);
54 #else /* Do encyryption */
55     if (passwd)
56         string_to_key(passwd, key);
57     else {
58         des_read_password(key, "Password: ", 0);
59     }
60 #endif /* NOENCRYPTION */
61 #endif /* unix */
62     return (0);
63 }
64
65 /*
66  * krb_get_pw_in_tkt() takes the name of the server for which the initial
67  * ticket is to be obtained, the name of the principal the ticket is
68  * for, the desired lifetime of the ticket, and the user's password.
69  * It passes its arguments on to krb_get_in_tkt(), which contacts
70  * Kerberos to get the ticket, decrypts it using the password provided,
71  * and stores it away for future use.
72  *
73  * On a Unix system, krb_get_pw_in_tkt() is able to prompt the user
74  * for a password, if the supplied password is null.  On a a non Unix
75  * system, it now requires the caller to supply a non-null password.
76  * This is because of the complexities of prompting the user in a
77  * non-terminal-oriented environment like the Macintosh (running in a
78  * driver) or MS-Windows (in a DLL).
79  *
80  * krb_get_pw_in_tkt() passes two additional arguments to krb_get_in_tkt():
81  * the name of a routine (passwd_to_key()) to be used to get the
82  * password in case the "password" argument is null and NULL for the
83  * decryption procedure indicating that krb_get_in_tkt should use the 
84  * default method of decrypting the response from the KDC.
85  *
86  * The result of the call to krb_get_in_tkt() is returned.
87  */
88
89 int INTERFACE
90 krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password)
91     char *user, *instance, *realm, *service, *sinstance;
92     int life;
93     char *password;
94 {
95 #if defined(_WINDOWS) || defined(macintosh)
96     /* In spite of the comments above, we don't allow that path here,
97        to simplify coding the non-UNIX clients. The only code that now
98        depends on this behavior is the preauth support, which has a
99        seperate function without this trap. Strictly speaking, this 
100        is an API change. */
101
102     if (password == 0)
103         return INTK_PW_NULL;
104 #endif
105
106     return(krb_get_in_tkt(user,instance,realm,service,sinstance,life,
107                           passwd_to_key,
108                           (decrypt_tkt_type)NULL, password));
109 }
110
111 /*
112  * krb_get_pw_in_tkt_preauth() gets handed the password or key explicitly,
113  * since the whole point of "pre" authentication is to prove that we've
114  * already got the key, and the only way to do that is to ask the user
115  * for it. Clearly we shouldn't ask twice.
116  */
117  
118 static C_Block old_key;
119
120 static int stub_key(user,instance,realm,passwd,key)
121     char *user, *instance, *realm, *passwd;
122     C_Block key;
123 {
124    (void) memcpy((char *) key, (char *) old_key, sizeof(old_key));
125    return 0;
126 }
127
128 int INTERFACE
129 krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password)
130     char *user, *instance, *realm, *service, *sinstance;
131     int life;
132     char *password;
133 {
134    char *preauth_p;
135    int   preauth_len;
136    int   ret_st;
137
138 #if defined(_WINDOWS) || defined(macintosh)
139    /* On non-Unix systems, we can't handle a null password, because
140       passwd_to_key can't handle prompting for the password.  */
141    if (password == 0)
142      return INTK_PW_NULL;
143 #endif
144
145    krb_mk_preauth(&preauth_p,&preauth_len, passwd_to_key,
146                   user,instance,realm,password,old_key);
147    ret_st = krb_get_in_tkt_preauth(user,instance,realm,service,sinstance,life,
148                                    (key_proc_type) stub_key,
149                                    (decrypt_tkt_type) NULL, password,
150                                    preauth_p, preauth_len);
151
152    krb_free_preauth(preauth_p, preauth_len);
153    return ret_st;
154 }
155
156 /* FIXME!  This routine belongs in the krb library and should simply
157    be shared between the encrypted and NOENCRYPTION versions!  */
158  
159 #ifdef NOENCRYPTION
160 /*
161  * This routine prints the supplied string to standard
162  * output as a prompt, and reads a password string without
163  * echoing.
164  */
165
166 #include <stdio.h>
167 #ifdef  BSDUNIX
168 #include <string.h>
169 #include <sys/ioctl.h>
170 #include <signal.h>
171 #include <setjmp.h>
172 #else
173 char     *strcpy();
174 int      strcmp();
175 #endif
176 #ifdef __svr4__
177 #include <sgtty.h>
178 #endif
179
180 #ifdef  BSDUNIX
181 static jmp_buf env;
182 #endif
183
184 #ifdef BSDUNIX
185 static void sig_restore();
186 static push_signals(), pop_signals();
187 int placebo_read_pw_string();
188 #endif
189
190 /*** Routines ****************************************************** */
191 int
192 placebo_read_password(k,prompt,verify)
193     des_cblock *k;
194     char *prompt;
195     int verify;
196 {
197     int ok;
198     char key_string[BUFSIZ];
199
200 #ifdef BSDUNIX
201     if (setjmp(env)) {
202         ok = -1;
203         goto lose;
204     }
205 #endif
206
207     ok = placebo_read_pw_string(key_string, BUFSIZ, prompt, verify);
208     if (ok == 0)
209         memset(k, 0, sizeof(C_Block));
210
211 lose:
212     memset(key_string, 0, sizeof (key_string));
213     return ok;
214 }
215
216 /*
217  * This version just returns the string, doesn't map to key.
218  *
219  * Returns 0 on success, non-zero on failure.
220  */
221
222 int
223 placebo_read_pw_string(s,max,prompt,verify)
224     char *s;
225     int max;
226     char *prompt;
227     int verify;
228 {
229     int ok = 0;
230     char *ptr;
231     
232 #ifdef BSDUNIX
233     jmp_buf old_env;
234     struct sgttyb tty_state;
235 #endif
236     char key_string[BUFSIZ];
237
238     if (max > BUFSIZ) {
239         return -1;
240     }
241
242 #ifdef  BSDUNIX
243     memcpy(env, old_env, sizeof(env));
244     if (setjmp(env))
245         goto lose;
246
247     /* save terminal state */
248     if (ioctl(0,TIOCGETP,&tty_state) == -1) 
249         return -1;
250
251     push_signals();
252     /* Turn off echo */
253     tty_state.sg_flags &= ~ECHO;
254     if (ioctl(0,TIOCSETP,&tty_state) == -1)
255         return -1;
256 #endif
257     while (!ok) {
258         printf(prompt);
259         fflush(stdout);
260 #ifdef  CROSSMSDOS
261         h19line(s,sizeof(s),0);
262         if (!strlen(s))
263             continue;
264 #else
265         if (!fgets(s, max, stdin)) {
266             clearerr(stdin);
267             continue;
268         }
269         if ((ptr = strchr(s, '\n')))
270             *ptr = '\0';
271 #endif
272         if (verify) {
273             printf("\nVerifying, please re-enter %s",prompt);
274             fflush(stdout);
275 #ifdef CROSSMSDOS
276             h19line(key_string,sizeof(key_string),0);
277             if (!strlen(key_string))
278                 continue;
279 #else
280             if (!fgets(key_string, sizeof(key_string), stdin)) {
281                 clearerr(stdin);
282                 continue;
283             }
284             if ((ptr = strchr(key_string, '\n')))
285             *ptr = '\0';
286 #endif
287             if (strcmp(s,key_string)) {
288                 printf("\n\07\07Mismatch - try again\n");
289                 fflush(stdout);
290                 continue;
291             }
292         }
293         ok = 1;
294     }
295
296 #ifdef  BSDUNIX
297 lose:
298     if (!ok)
299         memset(s, 0, max);
300     printf("\n");
301     /* turn echo back on */
302     tty_state.sg_flags |= ECHO;
303     if (ioctl(0,TIOCSETP,&tty_state))
304         ok = 0;
305     pop_signals();
306     memcpy(old_env, env, sizeof(env));
307 #endif
308     if (verify)
309         memset(key_string, 0, sizeof (key_string));
310     s[max-1] = 0;               /* force termination */
311     return !ok;                 /* return nonzero if not okay */
312 }
313
314 #ifdef  BSDUNIX
315 /*
316  * this can be static since we should never have more than
317  * one set saved....
318  */
319 static sigtype (*old_sigfunc[NSIG])();
320
321 static push_signals()
322 {
323     register i;
324     for (i = 0; i < NSIG; i++)
325         old_sigfunc[i] = signal(i,sig_restore);
326 }
327
328 static pop_signals()
329 {
330     register i;
331     for (i = 0; i < NSIG; i++)
332         signal(i,old_sigfunc[i]);
333 }
334
335 static void sig_restore(sig,code,scp)
336     int sig,code;
337     struct sigcontext *scp;
338 {
339     longjmp(env,1);
340 }
341 #endif
342 #endif /* NOENCRYPTION */