Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / appl / telnet / libtelnet / spx.c
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