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