1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 05/30/95";
10 #endif /* not lint */
11
12 /*
13 * Copyright (C) 1990 by the Massachusetts Institute of Technology
14 *
15 * Export of this software from the United States of America is assumed
16 * to require a specific license from the United States Government.
17 * It is the responsibility of any person or organization contemplating
18 * export to obtain such a license before exporting.
19 *
20 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
21 * distribute this software and its documentation for any purpose and
22 * without fee is hereby granted, provided that the above copyright
23 * notice appear in all copies and that both that copyright notice and
24 * this permission notice appear in supporting documentation, and that
25 * the name of M.I.T. not be used in advertising or publicity pertaining
26 * to distribution of the software without specific, written prior
27 * permission. M.I.T. makes no representations about the suitability of
28 * this software for any purpose. It is provided "as is" without express
29 * or implied warranty.
30 */
31
32
33 #if defined(AUTHENTICATION)
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <signal.h>
37 #define AUTH_NAMES
38 #include <arpa/telnet.h>
39 #ifdef __STDC__
40 #include <stdlib.h>
41 #endif
42 #ifdef NO_STRING_H
43 #include <strings.h>
44 #else
45 #include <string.h>
46 #endif
47
48 #include "encrypt.h"
49 #include "auth.h"
50 #include "misc-proto.h"
51 #include "auth-proto.h"
52
53 #define typemask(x) (1<<((x)-1))
54
55 #ifdef KRB4_ENCPWD
56 extern krb4encpwd_init();
57 extern krb4encpwd_send();
58 extern krb4encpwd_is();
59 extern krb4encpwd_reply();
60 extern krb4encpwd_status();
61 extern krb4encpwd_printsub();
62 #endif
63
64 #ifdef RSA_ENCPWD
65 extern rsaencpwd_init();
66 extern rsaencpwd_send();
67 extern rsaencpwd_is();
68 extern rsaencpwd_reply();
69 extern rsaencpwd_status();
70 extern rsaencpwd_printsub();
71 #endif
72
73 int auth_debug_mode = 0;
74 static char *Name = "Noname";
75 static int Server = 0;
76 static Authenticator *authenticated = 0;
77 static int authenticating = 0;
78 static int validuser = 0;
79 static unsigned char _auth_send_data[256];
80 static unsigned char *auth_send_data;
81 static int auth_send_cnt = 0;
82
83 /*
84 * Authentication types supported. Plese note that these are stored
85 * in priority order, i.e. try the first one first.
86 */
87 Authenticator authenticators[] = {
88 #ifdef SPX
89 { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
90 spx_init,
91 spx_send,
92 spx_is,
93 spx_reply,
94 spx_status,
95 spx_printsub },
96 { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
97 spx_init,
98 spx_send,
99 spx_is,
100 spx_reply,
101 spx_status,
102 spx_printsub },
103 #endif
104 #ifdef KRB5
105 # ifdef ENCRYPTION
106 { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
107 kerberos5_init,
108 kerberos5_send,
109 kerberos5_is,
110 kerberos5_reply,
111 kerberos5_status,
112 kerberos5_printsub },
113 # endif /* ENCRYPTION */
114 { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
115 kerberos5_init,
116 kerberos5_send,
117 kerberos5_is,
118 kerberos5_reply,
119 kerberos5_status,
120 kerberos5_printsub },
121 #endif
122 #ifdef KRB4
123 # ifdef ENCRYPTION
124 { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
125 kerberos4_init,
126 kerberos4_send,
127 kerberos4_is,
128 kerberos4_reply,
129 kerberos4_status,
130 kerberos4_printsub },
131 # endif /* ENCRYPTION */
132 { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
133 kerberos4_init,
134 kerberos4_send,
135 kerberos4_is,
136 kerberos4_reply,
137 kerberos4_status,
138 kerberos4_printsub },
139 #endif
140 #ifdef KRB4_ENCPWD
141 { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
142 krb4encpwd_init,
143 krb4encpwd_send,
144 krb4encpwd_is,
145 krb4encpwd_reply,
146 krb4encpwd_status,
147 krb4encpwd_printsub },
148 #endif
149 #ifdef RSA_ENCPWD
150 { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
151 rsaencpwd_init,
152 rsaencpwd_send,
153 rsaencpwd_is,
154 rsaencpwd_reply,
155 rsaencpwd_status,
156 rsaencpwd_printsub },
157 #endif
158 { 0, },
159 };
160
161 static Authenticator NoAuth = { 0 };
162
163 static int i_support = 0;
164 static int i_wont_support = 0;
165
166 Authenticator *
findauthenticator(type,way)167 findauthenticator(type, way)
168 int type;
169 int way;
170 {
171 Authenticator *ap = authenticators;
172
173 while (ap->type && (ap->type != type || ap->way != way))
174 ++ap;
175 return(ap->type ? ap : 0);
176 }
177
178 void
auth_init(name,server)179 auth_init(name, server)
180 char *name;
181 int server;
182 {
183 Authenticator *ap = authenticators;
184
185 Server = server;
186 Name = name;
187
188 i_support = 0;
189 authenticated = 0;
190 authenticating = 0;
191 while (ap->type) {
192 if (!ap->init || (*ap->init)(ap, server)) {
193 i_support |= typemask(ap->type);
194 if (auth_debug_mode)
195 printf(">>>%s: I support auth type %d %d\r\n",
196 Name,
197 ap->type, ap->way);
198 }
199 else if (auth_debug_mode)
200 printf(">>>%s: Init failed: auth type %d %d\r\n",
201 Name, ap->type, ap->way);
202 ++ap;
203 }
204 }
205
206 void
auth_disable_name(name)207 auth_disable_name(name)
208 char *name;
209 {
210 int x;
211 for (x = 0; x < AUTHTYPE_CNT; ++x) {
212 if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
213 i_wont_support |= typemask(x);
214 break;
215 }
216 }
217 }
218
219 int
getauthmask(type,maskp)220 getauthmask(type, maskp)
221 char *type;
222 int *maskp;
223 {
224 register int x;
225
226 if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
227 *maskp = -1;
228 return(1);
229 }
230
231 for (x = 1; x < AUTHTYPE_CNT; ++x) {
232 if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
233 *maskp = typemask(x);
234 return(1);
235 }
236 }
237 return(0);
238 }
239
240 int
auth_enable(type)241 auth_enable(type)
242 char *type;
243 {
244 return(auth_onoff(type, 1));
245 }
246
247 int
auth_disable(type)248 auth_disable(type)
249 char *type;
250 {
251 return(auth_onoff(type, 0));
252 }
253
254 int
auth_onoff(type,on)255 auth_onoff(type, on)
256 char *type;
257 int on;
258 {
259 int i, mask = -1;
260 Authenticator *ap;
261
262 if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
263 printf("auth %s 'type'\n", on ? "enable" : "disable");
264 printf("Where 'type' is one of:\n");
265 printf("\t%s\n", AUTHTYPE_NAME(0));
266 mask = 0;
267 for (ap = authenticators; ap->type; ap++) {
268 if ((mask & (i = typemask(ap->type))) != 0)
269 continue;
270 mask |= i;
271 printf("\t%s\n", AUTHTYPE_NAME(ap->type));
272 }
273 return(0);
274 }
275
276 if (!getauthmask(type, &mask)) {
277 printf("%s: invalid authentication type\n", type);
278 return(0);
279 }
280 if (on)
281 i_wont_support &= ~mask;
282 else
283 i_wont_support |= mask;
284 return(1);
285 }
286
287 int
auth_togdebug(on)288 auth_togdebug(on)
289 int on;
290 {
291 if (on < 0)
292 auth_debug_mode ^= 1;
293 else
294 auth_debug_mode = on;
295 printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
296 return(1);
297 }
298
299 int
auth_status()300 auth_status()
301 {
302 Authenticator *ap;
303 int i, mask;
304
305 if (i_wont_support == -1)
306 printf("Authentication disabled\n");
307 else
308 printf("Authentication enabled\n");
309
310 mask = 0;
311 for (ap = authenticators; ap->type; ap++) {
312 if ((mask & (i = typemask(ap->type))) != 0)
313 continue;
314 mask |= i;
315 printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
316 (i_wont_support & typemask(ap->type)) ?
317 "disabled" : "enabled");
318 }
319 return(1);
320 }
321
322 /*
323 * This routine is called by the server to start authentication
324 * negotiation.
325 */
326 void
auth_request()327 auth_request()
328 {
329 static unsigned char str_request[64] = { IAC, SB,
330 TELOPT_AUTHENTICATION,
331 TELQUAL_SEND, };
332 Authenticator *ap = authenticators;
333 unsigned char *e = str_request + 4;
334
335 if (!authenticating) {
336 authenticating = 1;
337 while (ap->type) {
338 if (i_support & ~i_wont_support & typemask(ap->type)) {
339 if (auth_debug_mode) {
340 printf(">>>%s: Sending type %d %d\r\n",
341 Name, ap->type, ap->way);
342 }
343 *e++ = ap->type;
344 *e++ = ap->way;
345 }
346 ++ap;
347 }
348 *e++ = IAC;
349 *e++ = SE;
350 net_write(str_request, e - str_request);
351 printsub('>', &str_request[2], e - str_request - 2);
352 }
353 }
354
355 /*
356 * This is called when an AUTH SEND is received.
357 * It should never arrive on the server side (as only the server can
358 * send an AUTH SEND).
359 * You should probably respond to it if you can...
360 *
361 * If you want to respond to the types out of order (i.e. even
362 * if he sends LOGIN KERBEROS and you support both, you respond
363 * with KERBEROS instead of LOGIN (which is against what the
364 * protocol says)) you will have to hack this code...
365 */
366 void
auth_send(data,cnt)367 auth_send(data, cnt)
368 unsigned char *data;
369 int cnt;
370 {
371 Authenticator *ap;
372 static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
373 TELQUAL_IS, AUTHTYPE_NULL, 0,
374 IAC, SE };
375 if (Server) {
376 if (auth_debug_mode) {
377 printf(">>>%s: auth_send called!\r\n", Name);
378 }
379 return;
380 }
381
382 if (auth_debug_mode) {
383 printf(">>>%s: auth_send got:", Name);
384 printd(data, cnt); printf("\r\n");
385 }
386
387 /*
388 * Save the data, if it is new, so that we can continue looking
389 * at it if the authorization we try doesn't work
390 */
391 if (data < _auth_send_data ||
392 data > _auth_send_data + sizeof(_auth_send_data)) {
393 auth_send_cnt = cnt > sizeof(_auth_send_data)
394 ? sizeof(_auth_send_data)
395 : cnt;
396 memmove((void *)_auth_send_data, (void *)data, auth_send_cnt);
397 auth_send_data = _auth_send_data;
398 } else {
399 /*
400 * This is probably a no-op, but we just make sure
401 */
402 auth_send_data = data;
403 auth_send_cnt = cnt;
404 }
405 while ((auth_send_cnt -= 2) >= 0) {
406 if (auth_debug_mode)
407 printf(">>>%s: He supports %d\r\n",
408 Name, *auth_send_data);
409 if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
410 ap = findauthenticator(auth_send_data[0],
411 auth_send_data[1]);
412 if (ap && ap->send) {
413 if (auth_debug_mode)
414 printf(">>>%s: Trying %d %d\r\n",
415 Name, auth_send_data[0],
416 auth_send_data[1]);
417 if ((*ap->send)(ap)) {
418 /*
419 * Okay, we found one we like
420 * and did it.
421 * we can go home now.
422 */
423 if (auth_debug_mode)
424 printf(">>>%s: Using type %d\r\n",
425 Name, *auth_send_data);
426 auth_send_data += 2;
427 return;
428 }
429 }
430 /* else
431 * just continue on and look for the
432 * next one if we didn't do anything.
433 */
434 }
435 auth_send_data += 2;
436 }
437 net_write(str_none, sizeof(str_none));
438 printsub('>', &str_none[2], sizeof(str_none) - 2);
439 if (auth_debug_mode)
440 printf(">>>%s: Sent failure message\r\n", Name);
441 auth_finished(0, AUTH_REJECT);
442 #ifdef KANNAN
443 /*
444 * We requested strong authentication, however no mechanisms worked.
445 * Therefore, exit on client end.
446 */
447 printf("Unable to securely authenticate user ... exit\n");
448 exit(0);
449 #endif /* KANNAN */
450 }
451
452 void
auth_send_retry()453 auth_send_retry()
454 {
455 /*
456 * if auth_send_cnt <= 0 then auth_send will end up rejecting
457 * the authentication and informing the other side of this.
458 */
459 auth_send(auth_send_data, auth_send_cnt);
460 }
461
462 void
auth_is(data,cnt)463 auth_is(data, cnt)
464 unsigned char *data;
465 int cnt;
466 {
467 Authenticator *ap;
468
469 if (cnt < 2)
470 return;
471
472 if (data[0] == AUTHTYPE_NULL) {
473 auth_finished(0, AUTH_REJECT);
474 return;
475 }
476
477 if (ap = findauthenticator(data[0], data[1])) {
478 if (ap->is)
479 (*ap->is)(ap, data+2, cnt-2);
480 } else if (auth_debug_mode)
481 printf(">>>%s: Invalid authentication in IS: %d\r\n",
482 Name, *data);
483 }
484
485 void
auth_reply(data,cnt)486 auth_reply(data, cnt)
487 unsigned char *data;
488 int cnt;
489 {
490 Authenticator *ap;
491
492 if (cnt < 2)
493 return;
494
495 if (ap = findauthenticator(data[0], data[1])) {
496 if (ap->reply)
497 (*ap->reply)(ap, data+2, cnt-2);
498 } else if (auth_debug_mode)
499 printf(">>>%s: Invalid authentication in SEND: %d\r\n",
500 Name, *data);
501 }
502
503 void
auth_name(data,cnt)504 auth_name(data, cnt)
505 unsigned char *data;
506 int cnt;
507 {
508 Authenticator *ap;
509 unsigned char savename[256];
510
511 if (cnt < 1) {
512 if (auth_debug_mode)
513 printf(">>>%s: Empty name in NAME\r\n", Name);
514 return;
515 }
516 if (cnt > sizeof(savename) - 1) {
517 if (auth_debug_mode)
518 printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
519 Name, cnt, sizeof(savename)-1);
520 return;
521 }
522 memmove((void *)savename, (void *)data, cnt);
523 savename[cnt] = '\0'; /* Null terminate */
524 if (auth_debug_mode)
525 printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
526 auth_encrypt_user(savename);
527 }
528
529 int
auth_sendname(cp,len)530 auth_sendname(cp, len)
531 unsigned char *cp;
532 int len;
533 {
534 static unsigned char str_request[256+6]
535 = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
536 register unsigned char *e = str_request + 4;
537 register unsigned char *ee = &str_request[sizeof(str_request)-2];
538
539 while (--len >= 0) {
540 if ((*e++ = *cp++) == IAC)
541 *e++ = IAC;
542 if (e >= ee)
543 return(0);
544 }
545 *e++ = IAC;
546 *e++ = SE;
547 net_write(str_request, e - str_request);
548 printsub('>', &str_request[2], e - &str_request[2]);
549 return(1);
550 }
551
552 void
auth_finished(ap,result)553 auth_finished(ap, result)
554 Authenticator *ap;
555 int result;
556 {
557 if (!(authenticated = ap))
558 authenticated = &NoAuth;
559 validuser = result;
560 }
561
562 /* ARGSUSED */
563 static void
auth_intr(sig)564 auth_intr(sig)
565 int sig;
566 {
567 auth_finished(0, AUTH_REJECT);
568 }
569
570 int
auth_wait(name)571 auth_wait(name)
572 char *name;
573 {
574 if (auth_debug_mode)
575 printf(">>>%s: in auth_wait.\r\n", Name);
576
577 if (Server && !authenticating)
578 return(0);
579
580 (void) signal(SIGALRM, auth_intr);
581 alarm(30);
582 while (!authenticated)
583 if (telnet_spin())
584 break;
585 alarm(0);
586 (void) signal(SIGALRM, SIG_DFL);
587
588 /*
589 * Now check to see if the user is valid or not
590 */
591 if (!authenticated || authenticated == &NoAuth)
592 return(AUTH_REJECT);
593
594 if (validuser == AUTH_VALID)
595 validuser = AUTH_USER;
596
597 if (authenticated->status)
598 validuser = (*authenticated->status)(authenticated,
599 name, validuser);
600 return(validuser);
601 }
602
603 void
auth_debug(mode)604 auth_debug(mode)
605 int mode;
606 {
607 auth_debug_mode = mode;
608 }
609
610 void
auth_printsub(data,cnt,buf,buflen)611 auth_printsub(data, cnt, buf, buflen)
612 unsigned char *data, *buf;
613 int cnt, buflen;
614 {
615 Authenticator *ap;
616
617 if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
618 (*ap->printsub)(data, cnt, buf, buflen);
619 else
620 auth_gen_printsub(data, cnt, buf, buflen);
621 }
622
623 void
auth_gen_printsub(data,cnt,buf,buflen)624 auth_gen_printsub(data, cnt, buf, buflen)
625 unsigned char *data, *buf;
626 int cnt, buflen;
627 {
628 register unsigned char *cp;
629 unsigned char tbuf[16];
630
631 cnt -= 3;
632 data += 3;
633 buf[buflen-1] = '\0';
634 buf[buflen-2] = '*';
635 buflen -= 2;
636 for (; cnt > 0; cnt--, data++) {
637 sprintf((char *)tbuf, " %d", *data);
638 for (cp = tbuf; *cp && buflen > 0; --buflen)
639 *buf++ = *cp++;
640 if (buflen <= 0)
641 return;
642 }
643 *buf = '\0';
644 }
645 #endif
646