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