xref: /titanic_51/usr/src/cmd/cmd-inet/usr.bin/ftp/auth.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate /*
9*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1985, 1989 Regents of the University of California.
10*7c478bd9Sstevel@tonic-gate  * All rights reserved.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
13*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
14*7c478bd9Sstevel@tonic-gate  * are met:
15*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
16*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
17*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
18*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
19*7c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
20*7c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
21*7c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
22*7c478bd9Sstevel@tonic-gate  *      This product includes software developed by the University of
23*7c478bd9Sstevel@tonic-gate  *      California, Berkeley and its contributors.
24*7c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor the names of its contributors
25*7c478bd9Sstevel@tonic-gate  *    may be used to endorse or promote products derived from this software
26*7c478bd9Sstevel@tonic-gate  *    without specific prior written permission.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29*7c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31*7c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32*7c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33*7c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34*7c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35*7c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36*7c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37*7c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38*7c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "ftp_var.h"
42*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
43*7c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
44*7c478bd9Sstevel@tonic-gate #include <gssapi/gssapi_ext.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate int	auth_type;	/* Authentication succeeded?  If so, what type? */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate char	*radix_error(int);
49*7c478bd9Sstevel@tonic-gate static void get_inet_addr_info(struct sockaddr_in6 *, gss_buffer_t);
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate static char *radixN =
52*7c478bd9Sstevel@tonic-gate 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
53*7c478bd9Sstevel@tonic-gate static char radix_pad = '=';
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate  * authenticate the user, if auth_type is AUTHTYPE_NONE
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  * Returns:	0 if there is no auth type
59*7c478bd9Sstevel@tonic-gate  *		1 if success
60*7c478bd9Sstevel@tonic-gate  * 		2 if failure
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate gss_OID		mechoid;
64*7c478bd9Sstevel@tonic-gate gss_ctx_id_t	gcontext;	/* global gss security context */
65*7c478bd9Sstevel@tonic-gate static		const char *gss_trials[] = { "ftp", "host" };
66*7c478bd9Sstevel@tonic-gate /* the number of elements in gss_trials array */
67*7c478bd9Sstevel@tonic-gate static const	int n_gss_trials = sizeof (gss_trials)/sizeof (char *);
68*7c478bd9Sstevel@tonic-gate char		*reply_parse;
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate int
71*7c478bd9Sstevel@tonic-gate do_auth(void)
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate 	int oldverbose = verbose;
74*7c478bd9Sstevel@tonic-gate 	uchar_t *out_buf = NULL;
75*7c478bd9Sstevel@tonic-gate 	size_t outlen;
76*7c478bd9Sstevel@tonic-gate 	int i;
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	if (auth_type != AUTHTYPE_NONE)
79*7c478bd9Sstevel@tonic-gate 	    return (1);		/* auth already succeeded */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	/* Other auth types go here ... */
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 	if (command("AUTH %s", "GSSAPI") == CONTINUE) {
84*7c478bd9Sstevel@tonic-gate 	    OM_uint32 maj_stat, min_stat;
85*7c478bd9Sstevel@tonic-gate 	    gss_name_t target_name;
86*7c478bd9Sstevel@tonic-gate 	    gss_buffer_desc send_tok, recv_tok, *token_ptr;
87*7c478bd9Sstevel@tonic-gate 	    gss_buffer_desc temp_buf;
88*7c478bd9Sstevel@tonic-gate 	    char stbuf[FTPBUFSIZ];
89*7c478bd9Sstevel@tonic-gate 	    int comcode, trial;
90*7c478bd9Sstevel@tonic-gate 	    int req_flags;
91*7c478bd9Sstevel@tonic-gate 	    struct gss_channel_bindings_struct chan;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	    get_inet_addr_info(&myctladdr, &temp_buf);
94*7c478bd9Sstevel@tonic-gate 	    chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
95*7c478bd9Sstevel@tonic-gate 	    chan.initiator_address.length =  temp_buf.length;
96*7c478bd9Sstevel@tonic-gate 	    chan.initiator_address.value = malloc(temp_buf.length);
97*7c478bd9Sstevel@tonic-gate 	    memcpy(chan.initiator_address.value, temp_buf.value,
98*7c478bd9Sstevel@tonic-gate 		temp_buf.length);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	    get_inet_addr_info(&remctladdr, &temp_buf);
101*7c478bd9Sstevel@tonic-gate 	    chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
102*7c478bd9Sstevel@tonic-gate 	    chan.acceptor_address.length = temp_buf.length;
103*7c478bd9Sstevel@tonic-gate 	    chan.acceptor_address.value = malloc(temp_buf.length);
104*7c478bd9Sstevel@tonic-gate 	    memcpy(chan.acceptor_address.value, temp_buf.value,
105*7c478bd9Sstevel@tonic-gate 		temp_buf.length);
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	    chan.application_data.length = 0;
108*7c478bd9Sstevel@tonic-gate 	    chan.application_data.value  = 0;
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 	    if (verbose)
111*7c478bd9Sstevel@tonic-gate 		(void) printf("GSSAPI accepted as authentication type\n");
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	    /* set the forward flag */
114*7c478bd9Sstevel@tonic-gate 	    req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	    if (fflag)
117*7c478bd9Sstevel@tonic-gate 		req_flags |= GSS_C_DELEG_FLAG;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	    /* blob from gss-client */
120*7c478bd9Sstevel@tonic-gate 	    for (trial = 0; trial < n_gss_trials; trial++) {
121*7c478bd9Sstevel@tonic-gate 		/* ftp@hostname first, then host@hostname */
122*7c478bd9Sstevel@tonic-gate 		/* the V5 GSSAPI binding canonicalizes this for us... */
123*7c478bd9Sstevel@tonic-gate 		(void) snprintf(stbuf, FTPBUFSIZ, "%s@%s",
124*7c478bd9Sstevel@tonic-gate 			gss_trials[trial], hostname);
125*7c478bd9Sstevel@tonic-gate 		if (debug)
126*7c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr,
127*7c478bd9Sstevel@tonic-gate 			"Trying to authenticate to <%s>\n", stbuf);
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 		send_tok.value = stbuf;
130*7c478bd9Sstevel@tonic-gate 		send_tok.length = strlen(stbuf) + 1;
131*7c478bd9Sstevel@tonic-gate 		maj_stat = gss_import_name(&min_stat, &send_tok,
132*7c478bd9Sstevel@tonic-gate 			GSS_C_NT_HOSTBASED_SERVICE, &target_name);
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 		if (maj_stat != GSS_S_COMPLETE) {
135*7c478bd9Sstevel@tonic-gate 		    user_gss_error(maj_stat, min_stat, "parsing name");
136*7c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr, "name parsed <%s>\n", stbuf);
137*7c478bd9Sstevel@tonic-gate 		    continue;
138*7c478bd9Sstevel@tonic-gate 		}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 		token_ptr = GSS_C_NO_BUFFER;
141*7c478bd9Sstevel@tonic-gate 		gcontext = GSS_C_NO_CONTEXT; /* structure copy */
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 		do {
144*7c478bd9Sstevel@tonic-gate 		    if (debug)
145*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
146*7c478bd9Sstevel@tonic-gate 				"calling gss_init_sec_context\n");
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 		    if (mechstr && !mechoid &&
149*7c478bd9Sstevel@tonic-gate 			__gss_mech_to_oid(mechstr, (gss_OID*)&mechoid) !=
150*7c478bd9Sstevel@tonic-gate 			GSS_S_COMPLETE)
151*7c478bd9Sstevel@tonic-gate 				(void) printf("do_auth: %s: not a valid "
152*7c478bd9Sstevel@tonic-gate 					"security mechanism\n", mechstr);
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		    if (!mechoid)
155*7c478bd9Sstevel@tonic-gate 			mechoid = GSS_C_NULL_OID;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 		    maj_stat = gss_init_sec_context(&min_stat,
158*7c478bd9Sstevel@tonic-gate 				    GSS_C_NO_CREDENTIAL,
159*7c478bd9Sstevel@tonic-gate 				    &gcontext,
160*7c478bd9Sstevel@tonic-gate 				    target_name,
161*7c478bd9Sstevel@tonic-gate 				    mechoid,
162*7c478bd9Sstevel@tonic-gate 				    req_flags,
163*7c478bd9Sstevel@tonic-gate 				    0,
164*7c478bd9Sstevel@tonic-gate 				    &chan,	/* channel bindings */
165*7c478bd9Sstevel@tonic-gate 				    token_ptr,
166*7c478bd9Sstevel@tonic-gate 				    NULL,	/* ignore mech type */
167*7c478bd9Sstevel@tonic-gate 				    &send_tok,
168*7c478bd9Sstevel@tonic-gate 				    NULL,	/* ignore ret_flags */
169*7c478bd9Sstevel@tonic-gate 				    NULL);	/* ignore time_rec */
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		    if (maj_stat != GSS_S_COMPLETE &&
172*7c478bd9Sstevel@tonic-gate 			maj_stat != GSS_S_CONTINUE_NEEDED) {
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 			/* return an error if this is NOT the ftp ticket */
175*7c478bd9Sstevel@tonic-gate 			if (strcmp(gss_trials[trial], "ftp"))
176*7c478bd9Sstevel@tonic-gate 				user_gss_error(maj_stat, min_stat,
177*7c478bd9Sstevel@tonic-gate 					"initializing context");
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 			(void) gss_release_name(&min_stat, &target_name);
180*7c478bd9Sstevel@tonic-gate 			/* could just be that we missed on the service name */
181*7c478bd9Sstevel@tonic-gate 			goto outer_loop;
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 		    }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		if (send_tok.length != 0) {
186*7c478bd9Sstevel@tonic-gate 		    int len = send_tok.length;
187*7c478bd9Sstevel@tonic-gate 		    reply_parse = "ADAT="; /* for command() later */
188*7c478bd9Sstevel@tonic-gate 		    oldverbose = verbose;
189*7c478bd9Sstevel@tonic-gate 		    verbose = (trial == n_gss_trials-1)?0:-1;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 		    outlen = ENCODELEN(send_tok.length);
192*7c478bd9Sstevel@tonic-gate 		    out_buf = (uchar_t *)malloc(outlen);
193*7c478bd9Sstevel@tonic-gate 		    if (out_buf == NULL) {
194*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "memory error allocating "
195*7c478bd9Sstevel@tonic-gate 				"auth buffer\n");
196*7c478bd9Sstevel@tonic-gate 			maj_stat = GSS_S_FAILURE;
197*7c478bd9Sstevel@tonic-gate 			goto outer_loop;
198*7c478bd9Sstevel@tonic-gate 		    }
199*7c478bd9Sstevel@tonic-gate 		    auth_error = radix_encode(send_tok.value, out_buf,
200*7c478bd9Sstevel@tonic-gate 			outlen, &len, 0);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 		    if (auth_error)  {
203*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Base 64 encoding failed: %s\n",
204*7c478bd9Sstevel@tonic-gate 				radix_error(auth_error));
205*7c478bd9Sstevel@tonic-gate 		    } else if ((comcode = command("ADAT %s", out_buf))
206*7c478bd9Sstevel@tonic-gate 			!= COMPLETE /* && comcode != 3 (335)*/) {
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 			if (trial == n_gss_trials-1) {
209*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr, "GSSAPI ADAT failed (%d)\n",
210*7c478bd9Sstevel@tonic-gate 				comcode);
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 			    /* force out of loop */
213*7c478bd9Sstevel@tonic-gate 			    maj_stat = GSS_S_FAILURE;
214*7c478bd9Sstevel@tonic-gate 			}
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 			/*
217*7c478bd9Sstevel@tonic-gate 			 * backoff to the v1 gssapi is still possible.
218*7c478bd9Sstevel@tonic-gate 			 * Send a new AUTH command.  If that fails,
219*7c478bd9Sstevel@tonic-gate 			 * terminate the loop
220*7c478bd9Sstevel@tonic-gate 			 */
221*7c478bd9Sstevel@tonic-gate 			if (command("AUTH %s", "GSSAPI") != CONTINUE) {
222*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
223*7c478bd9Sstevel@tonic-gate 				"GSSAPI ADAT failed, AUTH restart failed\n");
224*7c478bd9Sstevel@tonic-gate 			    /* force out of loop */
225*7c478bd9Sstevel@tonic-gate 			    maj_stat = GSS_S_FAILURE;
226*7c478bd9Sstevel@tonic-gate 			}
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 			goto outer_loop;
229*7c478bd9Sstevel@tonic-gate 		    } else if (!reply_parse) {
230*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
231*7c478bd9Sstevel@tonic-gate 			    "No authentication data received from server\n");
232*7c478bd9Sstevel@tonic-gate 			if (maj_stat == GSS_S_COMPLETE) {
233*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
234*7c478bd9Sstevel@tonic-gate 				"...but no more was needed\n");
235*7c478bd9Sstevel@tonic-gate 			    goto gss_complete_loop;
236*7c478bd9Sstevel@tonic-gate 			} else {
237*7c478bd9Sstevel@tonic-gate 			    user_gss_error(maj_stat, min_stat, "no reply.");
238*7c478bd9Sstevel@tonic-gate 			    goto gss_complete_loop;
239*7c478bd9Sstevel@tonic-gate 			}
240*7c478bd9Sstevel@tonic-gate 		    } else if (auth_error = radix_encode((uchar_t *)
241*7c478bd9Sstevel@tonic-gate 			reply_parse, out_buf, outlen, &i, 1)) {
242*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
243*7c478bd9Sstevel@tonic-gate 				"Base 64 decoding failed: %s\n",
244*7c478bd9Sstevel@tonic-gate 				radix_error(auth_error));
245*7c478bd9Sstevel@tonic-gate 		    } else {
246*7c478bd9Sstevel@tonic-gate 			/* everything worked */
247*7c478bd9Sstevel@tonic-gate 			token_ptr = &recv_tok;
248*7c478bd9Sstevel@tonic-gate 			recv_tok.value = out_buf;
249*7c478bd9Sstevel@tonic-gate 			recv_tok.length = i;
250*7c478bd9Sstevel@tonic-gate 			continue;
251*7c478bd9Sstevel@tonic-gate 		    } /* end if (auth_error) */
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate /* get out of loop clean */
254*7c478bd9Sstevel@tonic-gate gss_complete_loop:
255*7c478bd9Sstevel@tonic-gate 		    trial = n_gss_trials-1;
256*7c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, &send_tok);
257*7c478bd9Sstevel@tonic-gate 		    gss_release_name(&min_stat, &target_name);
258*7c478bd9Sstevel@tonic-gate 		    goto outer_loop;
259*7c478bd9Sstevel@tonic-gate 		} /* end if (send_tok.length != 0) */
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	    } while (maj_stat == GSS_S_CONTINUE_NEEDED);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate outer_loop:
264*7c478bd9Sstevel@tonic-gate 	    if (maj_stat == GSS_S_COMPLETE)
265*7c478bd9Sstevel@tonic-gate 		break;
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	    } /* end for loop */
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	    verbose = oldverbose;
270*7c478bd9Sstevel@tonic-gate 	    if (out_buf != NULL)
271*7c478bd9Sstevel@tonic-gate 		free(out_buf);
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	    if (maj_stat == GSS_S_COMPLETE) {
274*7c478bd9Sstevel@tonic-gate 		(void) printf("GSSAPI authentication succeeded\n");
275*7c478bd9Sstevel@tonic-gate 		reply_parse = NULL;
276*7c478bd9Sstevel@tonic-gate 		auth_type = AUTHTYPE_GSSAPI;
277*7c478bd9Sstevel@tonic-gate 		return (1);
278*7c478bd9Sstevel@tonic-gate 	    } else {
279*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "GSSAPI authentication failed\n");
280*7c478bd9Sstevel@tonic-gate 		reply_parse = NULL;
281*7c478bd9Sstevel@tonic-gate 	    }
282*7c478bd9Sstevel@tonic-gate 	} /* end if (command...) */
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	/* Other auth types go here ... */
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	return (0);
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate /*
290*7c478bd9Sstevel@tonic-gate  * Get the information for the channel structure.
291*7c478bd9Sstevel@tonic-gate  */
292*7c478bd9Sstevel@tonic-gate void
293*7c478bd9Sstevel@tonic-gate get_inet_addr_info(struct sockaddr_in6 *in_ipaddr, gss_buffer_t in_buffer)
294*7c478bd9Sstevel@tonic-gate {
295*7c478bd9Sstevel@tonic-gate 	size_t length;
296*7c478bd9Sstevel@tonic-gate 	char *value;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	if (in_ipaddr == NULL) {
299*7c478bd9Sstevel@tonic-gate 		in_buffer->length = 0;
300*7c478bd9Sstevel@tonic-gate 		in_buffer->value = NULL;
301*7c478bd9Sstevel@tonic-gate 		return;
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	/* get the initiator address.value and address.length */
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if (in_ipaddr->sin6_family == AF_INET6) {
307*7c478bd9Sstevel@tonic-gate 		struct in_addr in_ipv4addr;
308*7c478bd9Sstevel@tonic-gate 		struct sockaddr_in6 *sin6 =
309*7c478bd9Sstevel@tonic-gate 			(struct sockaddr_in6 *)in_ipaddr;
310*7c478bd9Sstevel@tonic-gate 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
311*7c478bd9Sstevel@tonic-gate 			IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
312*7c478bd9Sstevel@tonic-gate 				&in_ipv4addr);
313*7c478bd9Sstevel@tonic-gate 			in_buffer->length = length = sizeof (struct in_addr);
314*7c478bd9Sstevel@tonic-gate 			in_buffer->value = value = malloc(length);
315*7c478bd9Sstevel@tonic-gate 			memcpy(value, &in_ipv4addr, length);
316*7c478bd9Sstevel@tonic-gate 		} else {
317*7c478bd9Sstevel@tonic-gate 			in_buffer->length = length = sizeof (struct in6_addr);
318*7c478bd9Sstevel@tonic-gate 			in_buffer->value = value = malloc(length);
319*7c478bd9Sstevel@tonic-gate 			memcpy(value, &(sin6->sin6_addr.s6_addr),
320*7c478bd9Sstevel@tonic-gate 				length);
321*7c478bd9Sstevel@tonic-gate 		}
322*7c478bd9Sstevel@tonic-gate 	} else {
323*7c478bd9Sstevel@tonic-gate 		in_buffer->length = length = sizeof (struct in_addr);
324*7c478bd9Sstevel@tonic-gate 		in_buffer->value = value = malloc(in_buffer->length);
325*7c478bd9Sstevel@tonic-gate 		memcpy(value,
326*7c478bd9Sstevel@tonic-gate 			&((struct sockaddr_in *)(in_ipaddr))->sin_addr,
327*7c478bd9Sstevel@tonic-gate 			length);
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate int
332*7c478bd9Sstevel@tonic-gate radix_encode(uchar_t *inbuf, uchar_t *outbuf, size_t buflen,
333*7c478bd9Sstevel@tonic-gate 	int *outlen, int decode)
334*7c478bd9Sstevel@tonic-gate {
335*7c478bd9Sstevel@tonic-gate 	int i, j, D;
336*7c478bd9Sstevel@tonic-gate 	char *p;
337*7c478bd9Sstevel@tonic-gate 	uchar_t c;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	if (decode) {
340*7c478bd9Sstevel@tonic-gate 		for (i = j = 0;
341*7c478bd9Sstevel@tonic-gate 		    inbuf[i] && inbuf[i] != radix_pad && (j < buflen);
342*7c478bd9Sstevel@tonic-gate 		    i++) {
343*7c478bd9Sstevel@tonic-gate 		    if ((p = strchr(radixN, inbuf[i])) == NULL)
344*7c478bd9Sstevel@tonic-gate 			return (1);
345*7c478bd9Sstevel@tonic-gate 		    D = p - radixN;
346*7c478bd9Sstevel@tonic-gate 		    switch (i&3) {
347*7c478bd9Sstevel@tonic-gate 			case 0:
348*7c478bd9Sstevel@tonic-gate 			    outbuf[j] = D<<2;
349*7c478bd9Sstevel@tonic-gate 			    break;
350*7c478bd9Sstevel@tonic-gate 			case 1:
351*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] |= D>>4;
352*7c478bd9Sstevel@tonic-gate 			    outbuf[j] = (D&15)<<4;
353*7c478bd9Sstevel@tonic-gate 			    break;
354*7c478bd9Sstevel@tonic-gate 			case 2:
355*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] |= D>>2;
356*7c478bd9Sstevel@tonic-gate 			    outbuf[j] = (D&3)<<6;
357*7c478bd9Sstevel@tonic-gate 			    break;
358*7c478bd9Sstevel@tonic-gate 			case 3:
359*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] |= D;
360*7c478bd9Sstevel@tonic-gate 		    }
361*7c478bd9Sstevel@tonic-gate 		}
362*7c478bd9Sstevel@tonic-gate 		if (j == buflen && (inbuf[i] && inbuf[i] != radix_pad)) {
363*7c478bd9Sstevel@tonic-gate 			return (4);
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 		switch (i&3) {
366*7c478bd9Sstevel@tonic-gate 			case 1: return (3);
367*7c478bd9Sstevel@tonic-gate 			case 2: if (D&15)
368*7c478bd9Sstevel@tonic-gate 					return (3);
369*7c478bd9Sstevel@tonic-gate 				if (strcmp((char *)&inbuf[i], "=="))
370*7c478bd9Sstevel@tonic-gate 					return (2);
371*7c478bd9Sstevel@tonic-gate 				break;
372*7c478bd9Sstevel@tonic-gate 			case 3: if (D&3)
373*7c478bd9Sstevel@tonic-gate 					return (3);
374*7c478bd9Sstevel@tonic-gate 				if (strcmp((char *)&inbuf[i], "="))
375*7c478bd9Sstevel@tonic-gate 					return (2);
376*7c478bd9Sstevel@tonic-gate 		}
377*7c478bd9Sstevel@tonic-gate 		*outlen = j;
378*7c478bd9Sstevel@tonic-gate 	} else {
379*7c478bd9Sstevel@tonic-gate 		for (i = j = 0; i < *outlen && j < buflen; i++)
380*7c478bd9Sstevel@tonic-gate 		    switch (i%3) {
381*7c478bd9Sstevel@tonic-gate 			case 0:
382*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] = radixN[inbuf[i]>>2];
383*7c478bd9Sstevel@tonic-gate 			    c = (inbuf[i]&3)<<4;
384*7c478bd9Sstevel@tonic-gate 			    break;
385*7c478bd9Sstevel@tonic-gate 			case 1:
386*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] = radixN[c|inbuf[i]>>4];
387*7c478bd9Sstevel@tonic-gate 			    c = (inbuf[i]&15)<<2;
388*7c478bd9Sstevel@tonic-gate 			    break;
389*7c478bd9Sstevel@tonic-gate 			case 2:
390*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] = radixN[c|inbuf[i]>>6];
391*7c478bd9Sstevel@tonic-gate 			    outbuf[j++] = radixN[inbuf[i]&63];
392*7c478bd9Sstevel@tonic-gate 			    c = 0;
393*7c478bd9Sstevel@tonic-gate 		    }
394*7c478bd9Sstevel@tonic-gate 		if (j == buflen && i < *outlen) {
395*7c478bd9Sstevel@tonic-gate 			return (4);
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 		if (i%3)
398*7c478bd9Sstevel@tonic-gate 			outbuf[j++] = radixN[c];
399*7c478bd9Sstevel@tonic-gate 		switch (i%3) {
400*7c478bd9Sstevel@tonic-gate 			case 1:
401*7c478bd9Sstevel@tonic-gate 				outbuf[j++] = radix_pad;
402*7c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
403*7c478bd9Sstevel@tonic-gate 			case 2:
404*7c478bd9Sstevel@tonic-gate 				outbuf[j++] = radix_pad;
405*7c478bd9Sstevel@tonic-gate 				break;
406*7c478bd9Sstevel@tonic-gate 		}
407*7c478bd9Sstevel@tonic-gate 		outbuf[*outlen = j] = '\0';
408*7c478bd9Sstevel@tonic-gate 	}
409*7c478bd9Sstevel@tonic-gate 	return (0);
410*7c478bd9Sstevel@tonic-gate }
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate char *
413*7c478bd9Sstevel@tonic-gate radix_error(int e)
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	switch (e) {
416*7c478bd9Sstevel@tonic-gate 	    case 0:  return ("Success");
417*7c478bd9Sstevel@tonic-gate 	    case 1:  return ("Bad character in encoding");
418*7c478bd9Sstevel@tonic-gate 	    case 2:  return ("Encoding not properly padded");
419*7c478bd9Sstevel@tonic-gate 	    case 3:  return ("Decoded # of bits not a multiple of 8");
420*7c478bd9Sstevel@tonic-gate 	    case 4:  return ("Buffer size error");
421*7c478bd9Sstevel@tonic-gate 	    default: return ("Unknown error");
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate }
424