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