Sync usage with man page.
[netbsd-mini2440.git] / lib / libtelnet / spx.c
blobefb3b1bf612391012efe6c401b28339fa3815d13
1 /* $NetBSD: spx.c,v 1.6 2005/04/09 22:43:51 christos Exp $ */
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)spx.c 8.2 (Berkeley) 5/30/95";
37 #else
38 __RCSID("$NetBSD: spx.c,v 1.6 2005/04/09 22:43:51 christos Exp $");
39 #endif
40 #endif /* not lint */
42 #ifdef SPX
44 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
45 * ALL RIGHTS RESERVED
47 * "Digital Equipment Corporation authorizes the reproduction,
48 * distribution and modification of this software subject to the following
49 * restrictions:
51 * 1. Any partial or whole copy of this software, or any modification
52 * thereof, must include this copyright notice in its entirety.
54 * 2. This software is supplied "as is" with no warranty of any kind,
55 * expressed or implied, for any purpose, including any warranty of fitness
56 * or merchantibility. DIGITAL assumes no responsibility for the use or
57 * reliability of this software, nor promises to provide any form of
58 * support for it on any basis.
60 * 3. Distribution of this software is authorized only if no profit or
61 * remuneration of any kind is received in exchange for such distribution.
63 * 4. This software produces public key authentication certificates
64 * bearing an expiration date established by DIGITAL and RSA Data
65 * Security, Inc. It may cease to generate certificates after the expiration
66 * date. Any modification of this software that changes or defeats
67 * the expiration date or its effect is unauthorized.
69 * 5. Software that will renew or extend the expiration date of
70 * authentication certificates produced by this software may be obtained
71 * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
72 * 94065, (415)595-8782, or from DIGITAL"
76 #include <sys/types.h>
77 #include <arpa/telnet.h>
78 #include <stdio.h>
79 #include "gssapi_defs.h"
80 #include <stdlib.h>
81 #ifdef NO_STRING_H
82 #include <strings.h>
83 #else
84 #include <string.h>
85 #endif
87 #include <pwd.h>
88 #include "encrypt.h"
89 #include "auth.h"
90 #include "misc.h"
92 extern auth_debug_mode;
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, };
99 #define SPX_AUTH 0 /* Authentication data follows */
100 #define SPX_REJECT 1 /* Rejected (reason might follow) */
101 #define SPX_ACCEPT 2 /* Accepted */
103 #ifdef ENCRYPTION
104 static Block session_key = { 0 };
105 #endif /* ENCRYPTION */
106 static Schedule sched;
107 static Block challenge = { 0 };
110 /*******************************************************************/
112 gss_OID_set actual_mechs;
113 gss_OID actual_mech_type, output_name_type;
114 int major_status, status, msg_ctx = 0, new_status;
115 int req_flags = 0, ret_flags, lifetime_rec;
116 gss_cred_id_t gss_cred_handle;
117 gss_ctx_id_t actual_ctxhandle, context_handle;
118 gss_buffer_desc output_token, input_token, input_name_buffer;
119 gss_buffer_desc status_string;
120 gss_name_t desired_targname, src_name;
121 gss_channel_bindings input_chan_bindings;
122 char lhostname[GSS_C_MAX_PRINTABLE_NAME];
123 char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
124 int to_addr=0, from_addr=0;
125 char *address;
126 gss_buffer_desc fullname_buffer;
127 gss_OID fullname_type;
128 gss_cred_id_t gss_delegated_cred_handle;
130 /*******************************************************************/
134 static int
135 Data(ap, type, d, c)
136 Authenticator *ap;
137 int type;
138 void *d;
139 int c;
141 unsigned char *p = str_data + 4;
142 unsigned char *cd = (unsigned char *)d;
144 if (c == -1)
145 c = strlen((char *)cd);
147 if (0) {
148 printf("%s:%d: [%d] (%d)",
149 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
150 str_data[3],
151 type, c);
152 printd(d, c);
153 printf("\r\n");
155 *p++ = ap->type;
156 *p++ = ap->way;
157 *p++ = type;
158 while (c-- > 0) {
159 if ((*p++ = *cd++) == IAC)
160 *p++ = IAC;
162 *p++ = IAC;
163 *p++ = SE;
164 if (str_data[3] == TELQUAL_IS)
165 printsub('>', &str_data[2], p - (&str_data[2]));
166 return(telnet_net_write(str_data, p - str_data));
170 spx_init(ap, server)
171 Authenticator *ap;
172 int server;
174 gss_cred_id_t tmp_cred_handle;
176 if (server) {
177 str_data[3] = TELQUAL_REPLY;
178 gethostname(lhostname, sizeof(lhostname));
179 strlcpy(targ_printable, "SERVICE:rcmd@",
180 sizeof(targ_printable));
181 strlcat(targ_printable, lhostname, sizeof(targ_printable));
182 input_name_buffer.length = strlen(targ_printable);
183 input_name_buffer.value = targ_printable;
184 major_status = gss_import_name(&status,
185 &input_name_buffer,
186 GSS_C_NULL_OID,
187 &desired_targname);
188 major_status = gss_acquire_cred(&status,
189 desired_targname,
191 GSS_C_NULL_OID_SET,
192 GSS_C_ACCEPT,
193 &tmp_cred_handle,
194 &actual_mechs,
195 &lifetime_rec);
196 if (major_status != GSS_S_COMPLETE) return(0);
197 } else {
198 str_data[3] = TELQUAL_IS;
200 return(1);
204 spx_send(ap)
205 Authenticator *ap;
207 Block enckey;
208 int r;
210 gss_OID actual_mech_type, output_name_type;
211 int msg_ctx = 0, new_status, status;
212 int req_flags = 0, ret_flags, lifetime_rec, major_status;
213 gss_buffer_desc output_token, input_token, input_name_buffer;
214 gss_buffer_desc output_name_buffer, status_string;
215 gss_name_t desired_targname;
216 gss_channel_bindings input_chan_bindings;
217 char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
218 int from_addr=0, to_addr=0, myhostlen, j;
219 int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0;
220 char *address;
222 printf("[ Trying SPX ... ]\n");
223 strlcpy(targ_printable, "SERVICE:rcmd@", sizeof(targ_printable));
224 strlcat(targ_printable, RemoteHostName, sizeof(targ_printable));
226 input_name_buffer.length = strlen(targ_printable);
227 input_name_buffer.value = targ_printable;
229 if (!UserNameRequested) {
230 return(0);
233 major_status = gss_import_name(&status,
234 &input_name_buffer,
235 GSS_C_NULL_OID,
236 &desired_targname);
239 major_status = gss_display_name(&status,
240 desired_targname,
241 &output_name_buffer,
242 &output_name_type);
244 printf("target is '%s'\n", output_name_buffer.value); fflush(stdout);
246 major_status = gss_release_buffer(&status, &output_name_buffer);
248 input_chan_bindings = (gss_channel_bindings)
249 malloc(sizeof(gss_channel_bindings_desc));
251 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
252 input_chan_bindings->initiator_address.length = 4;
253 address = (char *) malloc(4);
254 input_chan_bindings->initiator_address.value = (char *) address;
255 address[0] = ((from_addr & 0xff000000) >> 24);
256 address[1] = ((from_addr & 0xff0000) >> 16);
257 address[2] = ((from_addr & 0xff00) >> 8);
258 address[3] = (from_addr & 0xff);
259 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
260 input_chan_bindings->acceptor_address.length = 4;
261 address = (char *) malloc(4);
262 input_chan_bindings->acceptor_address.value = (char *) address;
263 address[0] = ((to_addr & 0xff000000) >> 24);
264 address[1] = ((to_addr & 0xff0000) >> 16);
265 address[2] = ((to_addr & 0xff00) >> 8);
266 address[3] = (to_addr & 0xff);
267 input_chan_bindings->application_data.length = 0;
269 req_flags = 0;
270 if (deleg_flag) req_flags = req_flags | 1;
271 if (mutual_flag) req_flags = req_flags | 2;
272 if (replay_flag) req_flags = req_flags | 4;
273 if (seq_flag) req_flags = req_flags | 8;
275 major_status = gss_init_sec_context(&status, /* minor status */
276 GSS_C_NO_CREDENTIAL, /* cred handle */
277 &actual_ctxhandle, /* ctx handle */
278 desired_targname, /* target name */
279 GSS_C_NULL_OID, /* mech type */
280 req_flags, /* req flags */
281 0, /* time req */
282 input_chan_bindings, /* chan binding */
283 GSS_C_NO_BUFFER, /* input token */
284 &actual_mech_type, /* actual mech */
285 &output_token, /* output token */
286 &ret_flags, /* ret flags */
287 &lifetime_rec); /* time rec */
289 if ((major_status != GSS_S_COMPLETE) &&
290 (major_status != GSS_S_CONTINUE_NEEDED)) {
291 gss_display_status(&new_status,
292 status,
293 GSS_C_MECH_CODE,
294 GSS_C_NULL_OID,
295 &msg_ctx,
296 &status_string);
297 printf("%s\n", status_string.value);
298 return(0);
301 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
302 return(0);
305 if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) {
306 return(0);
309 return(1);
312 void
313 spx_is(ap, data, cnt)
314 Authenticator *ap;
315 unsigned char *data;
316 int cnt;
318 Session_Key skey;
319 Block datablock;
320 int r;
322 if (cnt-- < 1)
323 return;
324 switch (*data++) {
325 case SPX_AUTH:
326 input_token.length = cnt;
327 input_token.value = (char *) data;
329 gethostname(lhostname, sizeof(lhostname));
331 strlcpy(targ_printable, "SERVICE:rcmd@",
332 sizeof(targ_printable));
333 strlcat(targ_printable, lhostname, sizeof(targ_printable));
335 input_name_buffer.length = strlen(targ_printable);
336 input_name_buffer.value = targ_printable;
338 major_status = gss_import_name(&status,
339 &input_name_buffer,
340 GSS_C_NULL_OID,
341 &desired_targname);
343 major_status = gss_acquire_cred(&status,
344 desired_targname,
346 GSS_C_NULL_OID_SET,
347 GSS_C_ACCEPT,
348 &gss_cred_handle,
349 &actual_mechs,
350 &lifetime_rec);
352 major_status = gss_release_name(&status, desired_targname);
354 input_chan_bindings = (gss_channel_bindings)
355 malloc(sizeof(gss_channel_bindings_desc));
357 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
358 input_chan_bindings->initiator_address.length = 4;
359 address = (char *) malloc(4);
360 input_chan_bindings->initiator_address.value = (char *) address;
361 address[0] = ((from_addr & 0xff000000) >> 24);
362 address[1] = ((from_addr & 0xff0000) >> 16);
363 address[2] = ((from_addr & 0xff00) >> 8);
364 address[3] = (from_addr & 0xff);
365 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
366 input_chan_bindings->acceptor_address.length = 4;
367 address = (char *) malloc(4);
368 input_chan_bindings->acceptor_address.value = (char *) address;
369 address[0] = ((to_addr & 0xff000000) >> 24);
370 address[1] = ((to_addr & 0xff0000) >> 16);
371 address[2] = ((to_addr & 0xff00) >> 8);
372 address[3] = (to_addr & 0xff);
373 input_chan_bindings->application_data.length = 0;
375 major_status = gss_accept_sec_context(&status,
376 &context_handle,
377 gss_cred_handle,
378 &input_token,
379 input_chan_bindings,
380 &src_name,
381 &actual_mech_type,
382 &output_token,
383 &ret_flags,
384 &lifetime_rec,
385 &gss_delegated_cred_handle);
388 if (major_status != GSS_S_COMPLETE) {
390 major_status = gss_display_name(&status,
391 src_name,
392 &fullname_buffer,
393 &fullname_type);
394 Data(ap, SPX_REJECT, (void *)"auth failed", -1);
395 auth_finished(ap, AUTH_REJECT);
396 return;
399 major_status = gss_display_name(&status,
400 src_name,
401 &fullname_buffer,
402 &fullname_type);
405 Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length);
406 auth_finished(ap, AUTH_USER);
407 break;
409 default:
410 Data(ap, SPX_REJECT, 0, 0);
411 break;
416 void
417 spx_reply(ap, data, cnt)
418 Authenticator *ap;
419 unsigned char *data;
420 int cnt;
422 Session_Key skey;
424 if (cnt-- < 1)
425 return;
426 switch (*data++) {
427 case SPX_REJECT:
428 if (cnt > 0) {
429 printf("[ SPX refuses authentication because %.*s ]\r\n",
430 cnt, data);
431 } else
432 printf("[ SPX refuses authentication ]\r\n");
433 auth_send_retry();
434 return;
435 case SPX_ACCEPT:
436 printf("[ SPX accepts you ]\n");
437 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
439 * Send over the encrypted challenge.
441 input_token.value = (char *) data;
442 input_token.length = cnt;
444 major_status = gss_init_sec_context(&status, /* minor stat */
445 GSS_C_NO_CREDENTIAL, /* cred handle */
446 &actual_ctxhandle, /* ctx handle */
447 desired_targname, /* target name */
448 GSS_C_NULL_OID, /* mech type */
449 req_flags, /* req flags */
450 0, /* time req */
451 input_chan_bindings, /* chan binding */
452 &input_token, /* input token */
453 &actual_mech_type, /* actual mech */
454 &output_token, /* output token */
455 &ret_flags, /* ret flags */
456 &lifetime_rec); /* time rec */
458 if (major_status != GSS_S_COMPLETE) {
459 gss_display_status(&new_status,
460 status,
461 GSS_C_MECH_CODE,
462 GSS_C_NULL_OID,
463 &msg_ctx,
464 &status_string);
465 printf("[ SPX mutual response fails ... '%s' ]\r\n",
466 status_string.value);
467 auth_send_retry();
468 return;
471 auth_finished(ap, AUTH_USER);
472 return;
474 default:
475 return;
480 spx_status(ap, name, l, level)
481 Authenticator *ap;
482 char *name;
483 size_t l;
484 int level;
487 gss_buffer_desc fullname_buffer, acl_file_buffer;
488 gss_OID fullname_type;
489 char acl_file[160], fullname[160];
490 int major_status, status = 0;
491 struct passwd pws, *pwd;
492 char pwbuf[1024];
495 * hard code fullname to
496 * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
497 * and acl_file to "~kannan/.sphinx"
500 if (getpwnam_r(UserNameRequested, &pws, pwbuf, sizeof(pwbuf), &pwd)
501 != 0 || pwd == NULL) {
502 return(AUTH_USER); /* not authenticated */
505 strlcpy(acl_file, pwd->pw_dir, sizeof(acl_file));
506 strlcat(acl_file, "/.sphinx", sizeof(acl_file));
507 acl_file_buffer.value = acl_file;
508 acl_file_buffer.length = strlen(acl_file);
510 major_status = gss_display_name(&status,
511 src_name,
512 &fullname_buffer,
513 &fullname_type);
515 if (level < AUTH_USER)
516 return(level);
518 major_status = gss__check_acl(&status, &fullname_buffer,
519 &acl_file_buffer);
521 if (major_status == GSS_S_COMPLETE) {
522 strlcpy(name, UserNameRequested, l);
523 return(AUTH_VALID);
524 } else {
525 return(AUTH_USER);
530 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
531 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
533 void
534 spx_printsub(data, cnt, buf, buflen)
535 unsigned char *data, *buf;
536 int cnt, buflen;
538 char lbuf[32];
539 register int i;
541 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
542 buflen -= 1;
544 switch(data[3]) {
545 case SPX_REJECT: /* Rejected (reason might follow) */
546 strncpy((char *)buf, " REJECT ", buflen);
547 goto common;
549 case SPX_ACCEPT: /* Accepted (name might follow) */
550 strncpy((char *)buf, " ACCEPT ", buflen);
551 common:
552 BUMP(buf, buflen);
553 if (cnt <= 4)
554 break;
555 ADDC(buf, buflen, '"');
556 for (i = 4; i < cnt; i++)
557 ADDC(buf, buflen, data[i]);
558 ADDC(buf, buflen, '"');
559 ADDC(buf, buflen, '\0');
560 break;
562 case SPX_AUTH: /* Authentication data follows */
563 strncpy((char *)buf, " AUTH", buflen);
564 goto common2;
566 default:
567 snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[3]);
568 strncpy((char *)buf, lbuf, buflen);
569 common2:
570 BUMP(buf, buflen);
571 for (i = 4; i < cnt; i++) {
572 snprintf(lbuf, sizeof(lbuf), " %d", data[i]);
573 strncpy((char *)buf, lbuf, buflen);
574 BUMP(buf, buflen);
576 break;
580 #endif
582 #ifdef notdef
584 prkey(msg, key)
585 char *msg;
586 unsigned char *key;
588 register int i;
589 printf("%s:", msg);
590 for (i = 0; i < 8; i++)
591 printf(" %3d", key[i]);
592 printf("\r\n");
594 #endif