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