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