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