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