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