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