xref: /original-bsd/lib/libtelnet/spx.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)spx.c	8.1 (Berkeley) 06/04/93";
10 #endif /* not lint */
11 
12 #ifdef	SPX
13 /*
14  * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
15  * ALL RIGHTS RESERVED
16  *
17  * "Digital Equipment Corporation authorizes the reproduction,
18  * distribution and modification of this software subject to the following
19  * restrictions:
20  *
21  * 1.  Any partial or whole copy of this software, or any modification
22  * thereof, must include this copyright notice in its entirety.
23  *
24  * 2.  This software is supplied "as is" with no warranty of any kind,
25  * expressed or implied, for any purpose, including any warranty of fitness
26  * or merchantibility.  DIGITAL assumes no responsibility for the use or
27  * reliability of this software, nor promises to provide any form of
28  * support for it on any basis.
29  *
30  * 3.  Distribution of this software is authorized only if no profit or
31  * remuneration of any kind is received in exchange for such distribution.
32  *
33  * 4.  This software produces public key authentication certificates
34  * bearing an expiration date established by DIGITAL and RSA Data
35  * Security, Inc.  It may cease to generate certificates after the expiration
36  * date.  Any modification of this software that changes or defeats
37  * the expiration date or its effect is unauthorized.
38  *
39  * 5.  Software that will renew or extend the expiration date of
40  * authentication certificates produced by this software may be obtained
41  * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
42  * 94065, (415)595-8782, or from DIGITAL"
43  *
44  */
45 
46 #include <sys/types.h>
47 #include <arpa/telnet.h>
48 #include <stdio.h>
49 #include "gssapi_defs.h"
50 #ifdef	__STDC__
51 #include <stdlib.h>
52 #endif
53 #ifdef	NO_STRING_H
54 #include <strings.h>
55 #else
56 #include <string.h>
57 #endif
58 
59 #include <pwd.h>
60 #include "encrypt.h"
61 #include "auth.h"
62 #include "misc.h"
63 
64 extern auth_debug_mode;
65 
66 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
67 			  		AUTHTYPE_SPX, };
68 static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
69 					TELQUAL_NAME, };
70 
71 #define	SPX_AUTH	0		/* Authentication data follows */
72 #define	SPX_REJECT	1		/* Rejected (reason might follow) */
73 #define SPX_ACCEPT	2		/* Accepted */
74 
75 #ifdef	ENCRYPTION
76 static Block	session_key	= { 0 };
77 #endif	/* ENCRYPTION */
78 static Schedule sched;
79 static Block	challenge	= { 0 };
80 
81 
82 /*******************************************************************/
83 
84 gss_OID_set           actual_mechs;
85 gss_OID               actual_mech_type, output_name_type;
86 int                   major_status, status, msg_ctx = 0, new_status;
87 int                   req_flags = 0, ret_flags, lifetime_rec;
88 gss_cred_id_t         gss_cred_handle;
89 gss_ctx_id_t          actual_ctxhandle, context_handle;
90 gss_buffer_desc       output_token, input_token, input_name_buffer;
91 gss_buffer_desc       status_string;
92 gss_name_t            desired_targname, src_name;
93 gss_channel_bindings  input_chan_bindings;
94 char                  lhostname[GSS_C_MAX_PRINTABLE_NAME];
95 char                  targ_printable[GSS_C_MAX_PRINTABLE_NAME];
96 int                   to_addr=0, from_addr=0;
97 char                  *address;
98 gss_buffer_desc       fullname_buffer;
99 gss_OID               fullname_type;
100 gss_cred_id_t         gss_delegated_cred_handle;
101 
102 /*******************************************************************/
103 
104 
105 
106 	static int
107 Data(ap, type, d, c)
108 	Authenticator *ap;
109 	int type;
110 	void *d;
111 	int c;
112 {
113         unsigned char *p = str_data + 4;
114 	unsigned char *cd = (unsigned char *)d;
115 
116 	if (c == -1)
117 		c = strlen((char *)cd);
118 
119         if (0) {
120                 printf("%s:%d: [%d] (%d)",
121                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
122                         str_data[3],
123                         type, c);
124                 printd(d, c);
125                 printf("\r\n");
126         }
127 	*p++ = ap->type;
128 	*p++ = ap->way;
129 	*p++ = type;
130         while (c-- > 0) {
131                 if ((*p++ = *cd++) == IAC)
132                         *p++ = IAC;
133         }
134         *p++ = IAC;
135         *p++ = SE;
136 	if (str_data[3] == TELQUAL_IS)
137 		printsub('>', &str_data[2], p - (&str_data[2]));
138         return(net_write(str_data, p - str_data));
139 }
140 
141 	int
142 spx_init(ap, server)
143 	Authenticator *ap;
144 	int server;
145 {
146         gss_cred_id_t    tmp_cred_handle;
147 
148 	if (server) {
149 		str_data[3] = TELQUAL_REPLY;
150 		gethostname(lhostname, sizeof(lhostname));
151 		strcpy(targ_printable, "SERVICE:rcmd@");
152 		strcat(targ_printable, lhostname);
153 		input_name_buffer.length = strlen(targ_printable);
154 		input_name_buffer.value = targ_printable;
155 		major_status = gss_import_name(&status,
156                                        &input_name_buffer,
157                                        GSS_C_NULL_OID,
158                                        &desired_targname);
159 		major_status = gss_acquire_cred(&status,
160                                         desired_targname,
161                                         0,
162                                         GSS_C_NULL_OID_SET,
163                                         GSS_C_ACCEPT,
164                                         &tmp_cred_handle,
165                                         &actual_mechs,
166                                         &lifetime_rec);
167 		if (major_status != GSS_S_COMPLETE) return(0);
168 	} else {
169 		str_data[3] = TELQUAL_IS;
170 	}
171 	return(1);
172 }
173 
174 	int
175 spx_send(ap)
176 	Authenticator *ap;
177 {
178 	Block enckey;
179 	int r;
180 
181 	gss_OID  actual_mech_type, output_name_type;
182 	int           msg_ctx = 0, new_status, status;
183 	int           req_flags = 0, ret_flags, lifetime_rec, major_status;
184 	gss_buffer_desc  output_token, input_token, input_name_buffer;
185 	gss_buffer_desc  output_name_buffer, status_string;
186 	gss_name_t    desired_targname;
187 	gss_channel_bindings  input_chan_bindings;
188 	char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
189 	int  from_addr=0, to_addr=0, myhostlen, j;
190 	int  deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0;
191 	char *address;
192 
193 	printf("[ Trying SPX ... ]\n");
194 	strcpy(targ_printable, "SERVICE:rcmd@");
195 	strcat(targ_printable, RemoteHostName);
196 
197 	input_name_buffer.length = strlen(targ_printable);
198 	input_name_buffer.value = targ_printable;
199 
200 	if (!UserNameRequested) {
201 		return(0);
202 	}
203 
204 	major_status = gss_import_name(&status,
205 				       &input_name_buffer,
206 				       GSS_C_NULL_OID,
207 				       &desired_targname);
208 
209 
210 	major_status = gss_display_name(&status,
211 					desired_targname,
212 					&output_name_buffer,
213 					&output_name_type);
214 
215 	printf("target is '%s'\n", output_name_buffer.value); fflush(stdout);
216 
217 	major_status = gss_release_buffer(&status, &output_name_buffer);
218 
219 	input_chan_bindings = (gss_channel_bindings)
220 	  malloc(sizeof(gss_channel_bindings_desc));
221 
222 	input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
223 	input_chan_bindings->initiator_address.length = 4;
224 	address = (char *) malloc(4);
225 	input_chan_bindings->initiator_address.value = (char *) address;
226 	address[0] = ((from_addr & 0xff000000) >> 24);
227 	address[1] = ((from_addr & 0xff0000) >> 16);
228 	address[2] = ((from_addr & 0xff00) >> 8);
229 	address[3] = (from_addr & 0xff);
230 	input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
231 	input_chan_bindings->acceptor_address.length = 4;
232 	address = (char *) malloc(4);
233 	input_chan_bindings->acceptor_address.value = (char *) address;
234 	address[0] = ((to_addr & 0xff000000) >> 24);
235 	address[1] = ((to_addr & 0xff0000) >> 16);
236 	address[2] = ((to_addr & 0xff00) >> 8);
237 	address[3] = (to_addr & 0xff);
238 	input_chan_bindings->application_data.length = 0;
239 
240         req_flags = 0;
241         if (deleg_flag)  req_flags = req_flags | 1;
242         if (mutual_flag) req_flags = req_flags | 2;
243         if (replay_flag) req_flags = req_flags | 4;
244         if (seq_flag)    req_flags = req_flags | 8;
245 
246         major_status = gss_init_sec_context(&status,         /* minor status */
247 					GSS_C_NO_CREDENTIAL, /* cred handle */
248                                         &actual_ctxhandle,   /* ctx handle */
249                                         desired_targname,    /* target name */
250                                         GSS_C_NULL_OID,      /* mech type */
251                                         req_flags,           /* req flags */
252                                         0,                   /* time req */
253                                         input_chan_bindings, /* chan binding */
254                                         GSS_C_NO_BUFFER,     /* input token */
255                                         &actual_mech_type,   /* actual mech */
256                                         &output_token,       /* output token */
257                                         &ret_flags,          /* ret flags */
258                                         &lifetime_rec);      /* time rec */
259 
260 	if ((major_status != GSS_S_COMPLETE) &&
261 	    (major_status != GSS_S_CONTINUE_NEEDED)) {
262           gss_display_status(&new_status,
263                              status,
264                              GSS_C_MECH_CODE,
265                              GSS_C_NULL_OID,
266                              &msg_ctx,
267                              &status_string);
268           printf("%s\n", status_string.value);
269 	  return(0);
270 	}
271 
272 	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
273 		return(0);
274 	}
275 
276 	if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) {
277 		return(0);
278 	}
279 
280 	return(1);
281 }
282 
283 	void
284 spx_is(ap, data, cnt)
285 	Authenticator *ap;
286 	unsigned char *data;
287 	int cnt;
288 {
289 	Session_Key skey;
290 	Block datablock;
291 	int r;
292 
293 	if (cnt-- < 1)
294 		return;
295 	switch (*data++) {
296 	case SPX_AUTH:
297 	        input_token.length = cnt;
298 		input_token.value = (char *) data;
299 
300 		gethostname(lhostname, sizeof(lhostname));
301 
302 		strcpy(targ_printable, "SERVICE:rcmd@");
303 		strcat(targ_printable, lhostname);
304 
305 		input_name_buffer.length = strlen(targ_printable);
306 		input_name_buffer.value = targ_printable;
307 
308 		major_status = gss_import_name(&status,
309                                        &input_name_buffer,
310                                        GSS_C_NULL_OID,
311                                        &desired_targname);
312 
313 		major_status = gss_acquire_cred(&status,
314                                         desired_targname,
315                                         0,
316                                         GSS_C_NULL_OID_SET,
317                                         GSS_C_ACCEPT,
318                                         &gss_cred_handle,
319                                         &actual_mechs,
320                                         &lifetime_rec);
321 
322 		major_status = gss_release_name(&status, desired_targname);
323 
324 		input_chan_bindings = (gss_channel_bindings)
325 		  malloc(sizeof(gss_channel_bindings_desc));
326 
327 		input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
328 		input_chan_bindings->initiator_address.length = 4;
329 		address = (char *) malloc(4);
330 		input_chan_bindings->initiator_address.value = (char *) address;
331 		address[0] = ((from_addr & 0xff000000) >> 24);
332 		address[1] = ((from_addr & 0xff0000) >> 16);
333 		address[2] = ((from_addr & 0xff00) >> 8);
334 		address[3] = (from_addr & 0xff);
335 		input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
336 		input_chan_bindings->acceptor_address.length = 4;
337 		address = (char *) malloc(4);
338 		input_chan_bindings->acceptor_address.value = (char *) address;
339 		address[0] = ((to_addr & 0xff000000) >> 24);
340 		address[1] = ((to_addr & 0xff0000) >> 16);
341 		address[2] = ((to_addr & 0xff00) >> 8);
342 		address[3] = (to_addr & 0xff);
343 		input_chan_bindings->application_data.length = 0;
344 
345 		major_status = gss_accept_sec_context(&status,
346 					      &context_handle,
347                                               gss_cred_handle,
348                                               &input_token,
349                                               input_chan_bindings,
350                                               &src_name,
351                                               &actual_mech_type,
352                                               &output_token,
353                                               &ret_flags,
354                                               &lifetime_rec,
355                                               &gss_delegated_cred_handle);
356 
357 
358 		if (major_status != GSS_S_COMPLETE) {
359 
360 		  major_status = gss_display_name(&status,
361 					  src_name,
362                                           &fullname_buffer,
363                                           &fullname_type);
364 			Data(ap, SPX_REJECT, (void *)"auth failed", -1);
365 			auth_finished(ap, AUTH_REJECT);
366 			return;
367 		}
368 
369 		major_status = gss_display_name(&status,
370                                           src_name,
371                                           &fullname_buffer,
372                                           &fullname_type);
373 
374 
375 		Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length);
376 		auth_finished(ap, AUTH_USER);
377 		break;
378 
379 	default:
380 		Data(ap, SPX_REJECT, 0, 0);
381 		break;
382 	}
383 }
384 
385 
386 	void
387 spx_reply(ap, data, cnt)
388 	Authenticator *ap;
389 	unsigned char *data;
390 	int cnt;
391 {
392 	Session_Key skey;
393 
394 	if (cnt-- < 1)
395 		return;
396 	switch (*data++) {
397 	case SPX_REJECT:
398 		if (cnt > 0) {
399 			printf("[ SPX refuses authentication because %.*s ]\r\n",
400 				cnt, data);
401 		} else
402 			printf("[ SPX refuses authentication ]\r\n");
403 		auth_send_retry();
404 		return;
405 	case SPX_ACCEPT:
406 		printf("[ SPX accepts you ]\n");
407 		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
408 			/*
409 			 * Send over the encrypted challenge.
410 		 	 */
411 		  input_token.value = (char *) data;
412 		  input_token.length = cnt;
413 
414 		  major_status = gss_init_sec_context(&status, /* minor stat */
415                                         GSS_C_NO_CREDENTIAL, /* cred handle */
416                                         &actual_ctxhandle,   /* ctx handle */
417                                         desired_targname,    /* target name */
418                                         GSS_C_NULL_OID,      /* mech type */
419                                         req_flags,           /* req flags */
420                                         0,                   /* time req */
421                                         input_chan_bindings, /* chan binding */
422                                         &input_token,        /* input token */
423                                         &actual_mech_type,   /* actual mech */
424                                         &output_token,       /* output token */
425                                         &ret_flags,          /* ret flags */
426                                         &lifetime_rec);      /* time rec */
427 
428 		  if (major_status != GSS_S_COMPLETE) {
429 		    gss_display_status(&new_status,
430 				       status,
431 				       GSS_C_MECH_CODE,
432 				       GSS_C_NULL_OID,
433 				       &msg_ctx,
434 				       &status_string);
435 		    printf("[ SPX mutual response fails ... '%s' ]\r\n",
436 			 status_string.value);
437 		    auth_send_retry();
438 		    return;
439 		  }
440 		}
441 		auth_finished(ap, AUTH_USER);
442 		return;
443 
444 	default:
445 		return;
446 	}
447 }
448 
449 	int
450 spx_status(ap, name, level)
451 	Authenticator *ap;
452 	char *name;
453 	int level;
454 {
455 
456 	gss_buffer_desc  fullname_buffer, acl_file_buffer;
457 	gss_OID          fullname_type;
458         char acl_file[160], fullname[160];
459         int major_status, status = 0;
460 	struct passwd  *pwd;
461 
462         /*
463          * hard code fullname to
464          *   "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
465          * and acl_file to "~kannan/.sphinx"
466          */
467 
468 	pwd = getpwnam(UserNameRequested);
469 	if (pwd == NULL) {
470           return(AUTH_USER);   /*  not authenticated  */
471         }
472 
473 	strcpy(acl_file, pwd->pw_dir);
474 	strcat(acl_file, "/.sphinx");
475         acl_file_buffer.value = acl_file;
476         acl_file_buffer.length = strlen(acl_file);
477 
478 	major_status = gss_display_name(&status,
479 					src_name,
480 					&fullname_buffer,
481 					&fullname_type);
482 
483 	if (level < AUTH_USER)
484 		return(level);
485 
486         major_status = gss__check_acl(&status, &fullname_buffer,
487                                       &acl_file_buffer);
488 
489         if (major_status == GSS_S_COMPLETE) {
490 	  strcpy(name, UserNameRequested);
491 	  return(AUTH_VALID);
492         } else {
493            return(AUTH_USER);
494         }
495 
496 }
497 
498 #define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
499 #define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
500 
501 	void
502 spx_printsub(data, cnt, buf, buflen)
503 	unsigned char *data, *buf;
504 	int cnt, buflen;
505 {
506 	char lbuf[32];
507 	register int i;
508 
509 	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
510 	buflen -= 1;
511 
512 	switch(data[3]) {
513 	case SPX_REJECT:		/* Rejected (reason might follow) */
514 		strncpy((char *)buf, " REJECT ", buflen);
515 		goto common;
516 
517 	case SPX_ACCEPT:		/* Accepted (name might follow) */
518 		strncpy((char *)buf, " ACCEPT ", buflen);
519 	common:
520 		BUMP(buf, buflen);
521 		if (cnt <= 4)
522 			break;
523 		ADDC(buf, buflen, '"');
524 		for (i = 4; i < cnt; i++)
525 			ADDC(buf, buflen, data[i]);
526 		ADDC(buf, buflen, '"');
527 		ADDC(buf, buflen, '\0');
528 		break;
529 
530 	case SPX_AUTH:			/* Authentication data follows */
531 		strncpy((char *)buf, " AUTH", buflen);
532 		goto common2;
533 
534 	default:
535 		sprintf(lbuf, " %d (unknown)", data[3]);
536 		strncpy((char *)buf, lbuf, buflen);
537 	common2:
538 		BUMP(buf, buflen);
539 		for (i = 4; i < cnt; i++) {
540 			sprintf(lbuf, " %d", data[i]);
541 			strncpy((char *)buf, lbuf, buflen);
542 			BUMP(buf, buflen);
543 		}
544 		break;
545 	}
546 }
547 
548 #endif
549 
550 #ifdef notdef
551 
552 prkey(msg, key)
553 	char *msg;
554 	unsigned char *key;
555 {
556 	register int i;
557 	printf("%s:", msg);
558 	for (i = 0; i < 8; i++)
559 		printf(" %3d", key[i]);
560 	printf("\r\n");
561 }
562 #endif
563