]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - crypto/heimdal/appl/telnet/libtelnet/spx.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / crypto / heimdal / 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$");
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", (int)output_name_buffer.length,
241                                         (char*)output_name_buffer.value);
242         fflush(stdout);
243
244         major_status = gss_release_buffer(&status, &output_name_buffer);
245
246         input_chan_bindings = (gss_channel_bindings)
247           malloc(sizeof(gss_channel_bindings_desc));
248
249         input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
250         input_chan_bindings->initiator_address.length = 4;
251         address = (char *) malloc(4);
252         input_chan_bindings->initiator_address.value = (char *) address;
253         address[0] = ((from_addr & 0xff000000) >> 24);
254         address[1] = ((from_addr & 0xff0000) >> 16);
255         address[2] = ((from_addr & 0xff00) >> 8);
256         address[3] = (from_addr & 0xff);
257         input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
258         input_chan_bindings->acceptor_address.length = 4;
259         address = (char *) malloc(4);
260         input_chan_bindings->acceptor_address.value = (char *) address;
261         address[0] = ((to_addr & 0xff000000) >> 24);
262         address[1] = ((to_addr & 0xff0000) >> 16);
263         address[2] = ((to_addr & 0xff00) >> 8);
264         address[3] = (to_addr & 0xff);
265         input_chan_bindings->application_data.length = 0;
266
267         req_flags = 0;
268         if (deleg_flag)  req_flags = req_flags | 1;
269         if (mutual_flag) req_flags = req_flags | 2;
270         if (replay_flag) req_flags = req_flags | 4;
271         if (seq_flag)    req_flags = req_flags | 8;
272
273         major_status = gss_init_sec_context(&status,         /* minor status */
274                                         GSS_C_NO_CREDENTIAL, /* cred handle */
275                                         &actual_ctxhandle,   /* ctx handle */
276                                         desired_targname,    /* target name */
277                                         GSS_C_NULL_OID,      /* mech type */
278                                         req_flags,           /* req flags */
279                                         0,                   /* time req */
280                                         input_chan_bindings, /* chan binding */
281                                         GSS_C_NO_BUFFER,     /* input token */
282                                         &actual_mech_type,   /* actual mech */
283                                         &output_token,       /* output token */
284                                         &ret_flags,          /* ret flags */
285                                         &lifetime_rec);      /* time rec */
286
287         if ((major_status != GSS_S_COMPLETE) &&
288             (major_status != GSS_S_CONTINUE_NEEDED)) {
289           gss_display_status(&new_status,
290                                 status,
291                                 GSS_C_MECH_CODE,
292                                 GSS_C_NULL_OID,
293                                 &msg_ctx,
294                                 &status_string);
295           printf("%.*s\n", (int)status_string.length,
296                                 (char*)status_string.value);
297           return(0);
298         }
299
300         if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
301                 return(0);
302         }
303
304         if (!Data(ap, SPX_AUTH, output_token.value, output_token.length)) {
305                 return(0);
306         }
307
308         return(1);
309 }
310
311         void
312 spx_is(ap, data, cnt)
313         Authenticator *ap;
314         unsigned char *data;
315         int cnt;
316 {
317         Session_Key skey;
318         des_cblock datablock;
319         int r;
320
321         if (cnt-- < 1)
322                 return;
323         switch (*data++) {
324         case SPX_AUTH:
325                 input_token.length = cnt;
326                 input_token.value = (char *) data;
327
328                 gethostname(lhostname, sizeof(lhostname));
329
330                 snprintf(targ_printable, sizeof(targ_printable),
331                          "SERVICE:rcmd@%s", lhostname);
332
333                 input_name_buffer.length = strlen(targ_printable);
334                 input_name_buffer.value = targ_printable;
335
336                 major_status = gss_import_name(&status,
337                                         &input_name_buffer,
338                                         GSS_C_NULL_OID,
339                                         &desired_targname);
340
341                 major_status = gss_acquire_cred(&status,
342                                         desired_targname,
343                                         0,
344                                         GSS_C_NULL_OID_SET,
345                                         GSS_C_ACCEPT,
346                                         &gss_cred_handle,
347                                         &actual_mechs,
348                                         &lifetime_rec);
349
350                 major_status = gss_release_name(&status, desired_targname);
351
352                 input_chan_bindings = (gss_channel_bindings)
353                   malloc(sizeof(gss_channel_bindings_desc));
354
355                 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
356                 input_chan_bindings->initiator_address.length = 4;
357                 address = (char *) malloc(4);
358                 input_chan_bindings->initiator_address.value = (char *) address;
359                 address[0] = ((from_addr & 0xff000000) >> 24);
360                 address[1] = ((from_addr & 0xff0000) >> 16);
361                 address[2] = ((from_addr & 0xff00) >> 8);
362                 address[3] = (from_addr & 0xff);
363                 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
364                 input_chan_bindings->acceptor_address.length = 4;
365                 address = (char *) malloc(4);
366                 input_chan_bindings->acceptor_address.value = (char *) address;
367                 address[0] = ((to_addr & 0xff000000) >> 24);
368                 address[1] = ((to_addr & 0xff0000) >> 16);
369                 address[2] = ((to_addr & 0xff00) >> 8);
370                 address[3] = (to_addr & 0xff);
371                 input_chan_bindings->application_data.length = 0;
372
373                 major_status = gss_accept_sec_context(&status,
374                                                 &context_handle,
375                                                 gss_cred_handle,
376                                                 &input_token,
377                                                 input_chan_bindings,
378                                                 &src_name,
379                                                 &actual_mech_type,
380                                                 &output_token,
381                                                 &ret_flags,
382                                                 &lifetime_rec,
383                                                 &gss_delegated_cred_handle);
384
385
386                 if (major_status != GSS_S_COMPLETE) {
387
388                   major_status = gss_display_name(&status,
389                                         src_name,
390                                         &fullname_buffer,
391                                         &fullname_type);
392                         Data(ap, SPX_REJECT, "auth failed", -1);
393                         auth_finished(ap, AUTH_REJECT);
394                         return;
395                 }
396
397                 major_status = gss_display_name(&status,
398                                         src_name,
399                                         &fullname_buffer,
400                                         &fullname_type);
401
402
403                 Data(ap, SPX_ACCEPT, output_token.value, output_token.length);
404                 auth_finished(ap, AUTH_USER);
405                 break;
406
407         default:
408                 Data(ap, SPX_REJECT, 0, 0);
409                 break;
410         }
411 }
412
413
414         void
415 spx_reply(ap, data, cnt)
416         Authenticator *ap;
417         unsigned char *data;
418         int cnt;
419 {
420         Session_Key skey;
421
422         if (cnt-- < 1)
423                 return;
424         switch (*data++) {
425         case SPX_REJECT:
426                 if (cnt > 0) {
427                         printf("[ SPX refuses authentication because %.*s ]\r\n",
428                                 cnt, data);
429                 } else
430                         printf("[ SPX refuses authentication ]\r\n");
431                 auth_send_retry();
432                 return;
433         case SPX_ACCEPT:
434                 printf("[ SPX accepts you ]\r\n");
435                 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
436                         /*
437                          * Send over the encrypted challenge.
438                          */
439                   input_token.value = (char *) data;
440                   input_token.length = cnt;
441
442                   major_status = gss_init_sec_context(&status, /* minor stat */
443                                         GSS_C_NO_CREDENTIAL, /* cred handle */
444                                         &actual_ctxhandle,   /* ctx handle */
445                                         desired_targname,    /* target name */
446                                         GSS_C_NULL_OID,      /* mech type */
447                                         req_flags,           /* req flags */
448                                         0,                   /* time req */
449                                         input_chan_bindings, /* chan binding */
450                                         &input_token,        /* input token */
451                                         &actual_mech_type,   /* actual mech */
452                                         &output_token,       /* output token */
453                                         &ret_flags,          /* ret flags */
454                                         &lifetime_rec);      /* time rec */
455
456                   if (major_status != GSS_S_COMPLETE) {
457                     gss_display_status(&new_status,
458                                         status,
459                                         GSS_C_MECH_CODE,
460                                         GSS_C_NULL_OID,
461                                         &msg_ctx,
462                                         &status_string);
463                     printf("[ SPX mutual response fails ... '%.*s' ]\r\n",
464                          (int)status_string.length,
465                          (char*)status_string.value);
466                     auth_send_retry();
467                     return;
468                   }
469                 }
470                 auth_finished(ap, AUTH_USER);
471                 return;
472
473         default:
474                 return;
475         }
476 }
477
478         int
479 spx_status(ap, name, name_sz, level)
480         Authenticator *ap;
481         char *name;
482         size_t name_sz;
483         int level;
484 {
485
486         gss_buffer_desc  fullname_buffer, acl_file_buffer;
487         gss_OID          fullname_type;
488         char acl_file[160], fullname[160];
489         int major_status, status = 0;
490         struct passwd  *pwd;
491
492         /*
493          * hard code fullname to
494          *   "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
495          * and acl_file to "~kannan/.sphinx"
496          */
497
498         pwd = k_getpwnam(UserNameRequested);
499         if (pwd == NULL) {
500           return(AUTH_USER);   /*  not authenticated  */
501         }
502
503         snprintf (acl_file, sizeof(acl_file),
504                   "%s/.sphinx", pwd->pw_dir);
505
506         acl_file_buffer.value = acl_file;
507         acl_file_buffer.length = strlen(acl_file);
508
509         major_status = gss_display_name(&status,
510                                         src_name,
511                                         &fullname_buffer,
512                                         &fullname_type);
513
514         if (level < AUTH_USER)
515                 return(level);
516
517         major_status = gss__check_acl(&status, &fullname_buffer,
518                                         &acl_file_buffer);
519
520         if (major_status == GSS_S_COMPLETE) {
521           strlcpy(name, UserNameRequested, name_sz);
522           return(AUTH_VALID);
523         } else {
524            return(AUTH_USER);
525         }
526
527 }
528
529 #define BUMP(buf, len)          while (*(buf)) {++(buf), --(len);}
530 #define ADDC(buf, len, c)       if ((len) > 0) {*(buf)++ = (c); --(len);}
531
532         void
533 spx_printsub(unsigned char *data, size_t cnt,
534              unsigned char *buf, size_t buflen)
535 {
536         size_t i;
537
538         buf[buflen-1] = '\0';           /* make sure it's NULL terminated */
539         buflen -= 1;
540
541         switch(data[3]) {
542         case SPX_REJECT:                /* Rejected (reason might follow) */
543                 strlcpy((char *)buf, " REJECT ", buflen);
544                 goto common;
545
546         case SPX_ACCEPT:                /* Accepted (name might follow) */
547                 strlcpy((char *)buf, " ACCEPT ", buflen);
548         common:
549                 BUMP(buf, buflen);
550                 if (cnt <= 4)
551                         break;
552                 ADDC(buf, buflen, '"');
553                 for (i = 4; i < cnt; i++)
554                         ADDC(buf, buflen, data[i]);
555                 ADDC(buf, buflen, '"');
556                 ADDC(buf, buflen, '\0');
557                 break;
558
559         case SPX_AUTH:                  /* Authentication data follows */
560                 strlcpy((char *)buf, " AUTH", buflen);
561                 goto common2;
562
563         default:
564                 snprintf(buf, buflen, " %d (unknown)", data[3]);
565         common2:
566                 BUMP(buf, buflen);
567                 for (i = 4; i < cnt; i++) {
568                         snprintf(buf, buflen, " %d", data[i]);
569                         BUMP(buf, buflen);
570                 }
571                 break;
572         }
573 }
574
575 #endif
576
577 #ifdef notdef
578
579 prkey(msg, key)
580         char *msg;
581         unsigned char *key;
582 {
583         int i;
584         printf("%s:", msg);
585         for (i = 0; i < 8; i++)
586                 printf(" %3d", key[i]);
587         printf("\r\n");
588 }
589 #endif