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