xref: /original-bsd/lib/libtelnet/spx.c (revision c4f3b704)
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.2 (Berkeley) 05/30/95";
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
Data(ap,type,d,c)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
spx_init(ap,server)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
spx_send(ap)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
spx_is(ap,data,cnt)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
spx_reply(ap,data,cnt)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
spx_status(ap,name,level)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
spx_printsub(data,cnt,buf,buflen)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 
prkey(msg,key)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