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