xref: /aosp_15_r20/external/curl/lib/socks_gssapi.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Markus Moeller, <[email protected]>
10*6236dae4SAndroid Build Coastguard Worker  *
11*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker  *
15*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker  *
19*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker  *
22*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker  *
24*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
27*6236dae4SAndroid Build Coastguard Worker 
28*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY)
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker #include "curl_gssapi.h"
31*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
32*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
33*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
34*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
35*6236dae4SAndroid Build Coastguard Worker #include "timeval.h"
36*6236dae4SAndroid Build Coastguard Worker #include "socks.h"
37*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
38*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
39*6236dae4SAndroid Build Coastguard Worker 
40*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
41*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
42*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
43*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
44*6236dae4SAndroid Build Coastguard Worker 
45*6236dae4SAndroid Build Coastguard Worker #define MAX_GSS_LEN 1024
46*6236dae4SAndroid Build Coastguard Worker 
47*6236dae4SAndroid Build Coastguard Worker static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
48*6236dae4SAndroid Build Coastguard Worker 
49*6236dae4SAndroid Build Coastguard Worker /*
50*6236dae4SAndroid Build Coastguard Worker  * Helper GSS-API error functions.
51*6236dae4SAndroid Build Coastguard Worker  */
check_gss_err(struct Curl_easy * data,OM_uint32 major_status,OM_uint32 minor_status,const char * function)52*6236dae4SAndroid Build Coastguard Worker static int check_gss_err(struct Curl_easy *data,
53*6236dae4SAndroid Build Coastguard Worker                          OM_uint32 major_status,
54*6236dae4SAndroid Build Coastguard Worker                          OM_uint32 minor_status,
55*6236dae4SAndroid Build Coastguard Worker                          const char *function)
56*6236dae4SAndroid Build Coastguard Worker {
57*6236dae4SAndroid Build Coastguard Worker   if(GSS_ERROR(major_status)) {
58*6236dae4SAndroid Build Coastguard Worker     OM_uint32 maj_stat, min_stat;
59*6236dae4SAndroid Build Coastguard Worker     OM_uint32 msg_ctx = 0;
60*6236dae4SAndroid Build Coastguard Worker     gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
61*6236dae4SAndroid Build Coastguard Worker     struct dynbuf dbuf;
62*6236dae4SAndroid Build Coastguard Worker 
63*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_init(&dbuf, MAX_GSS_LEN);
64*6236dae4SAndroid Build Coastguard Worker     msg_ctx = 0;
65*6236dae4SAndroid Build Coastguard Worker     while(!msg_ctx) {
66*6236dae4SAndroid Build Coastguard Worker       /* convert major status code (GSS-API error) to text */
67*6236dae4SAndroid Build Coastguard Worker       maj_stat = gss_display_status(&min_stat, major_status,
68*6236dae4SAndroid Build Coastguard Worker                                     GSS_C_GSS_CODE,
69*6236dae4SAndroid Build Coastguard Worker                                     GSS_C_NULL_OID,
70*6236dae4SAndroid Build Coastguard Worker                                     &msg_ctx, &status_string);
71*6236dae4SAndroid Build Coastguard Worker       if(maj_stat == GSS_S_COMPLETE) {
72*6236dae4SAndroid Build Coastguard Worker         if(Curl_dyn_addn(&dbuf, status_string.value,
73*6236dae4SAndroid Build Coastguard Worker                          status_string.length))
74*6236dae4SAndroid Build Coastguard Worker           return 1; /* error */
75*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&min_stat, &status_string);
76*6236dae4SAndroid Build Coastguard Worker         break;
77*6236dae4SAndroid Build Coastguard Worker       }
78*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&min_stat, &status_string);
79*6236dae4SAndroid Build Coastguard Worker     }
80*6236dae4SAndroid Build Coastguard Worker     if(Curl_dyn_addn(&dbuf, ".\n", 2))
81*6236dae4SAndroid Build Coastguard Worker       return 1; /* error */
82*6236dae4SAndroid Build Coastguard Worker     msg_ctx = 0;
83*6236dae4SAndroid Build Coastguard Worker     while(!msg_ctx) {
84*6236dae4SAndroid Build Coastguard Worker       /* convert minor status code (underlying routine error) to text */
85*6236dae4SAndroid Build Coastguard Worker       maj_stat = gss_display_status(&min_stat, minor_status,
86*6236dae4SAndroid Build Coastguard Worker                                     GSS_C_MECH_CODE,
87*6236dae4SAndroid Build Coastguard Worker                                     GSS_C_NULL_OID,
88*6236dae4SAndroid Build Coastguard Worker                                     &msg_ctx, &status_string);
89*6236dae4SAndroid Build Coastguard Worker       if(maj_stat == GSS_S_COMPLETE) {
90*6236dae4SAndroid Build Coastguard Worker         if(Curl_dyn_addn(&dbuf, status_string.value,
91*6236dae4SAndroid Build Coastguard Worker                          status_string.length))
92*6236dae4SAndroid Build Coastguard Worker           return 1; /* error */
93*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&min_stat, &status_string);
94*6236dae4SAndroid Build Coastguard Worker         break;
95*6236dae4SAndroid Build Coastguard Worker       }
96*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&min_stat, &status_string);
97*6236dae4SAndroid Build Coastguard Worker     }
98*6236dae4SAndroid Build Coastguard Worker     failf(data, "GSS-API error: %s failed: %s", function, Curl_dyn_ptr(&dbuf));
99*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&dbuf);
100*6236dae4SAndroid Build Coastguard Worker     return 1;
101*6236dae4SAndroid Build Coastguard Worker   }
102*6236dae4SAndroid Build Coastguard Worker 
103*6236dae4SAndroid Build Coastguard Worker   return 0;
104*6236dae4SAndroid Build Coastguard Worker }
105*6236dae4SAndroid Build Coastguard Worker 
Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter * cf,struct Curl_easy * data)106*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
107*6236dae4SAndroid Build Coastguard Worker                                       struct Curl_easy *data)
108*6236dae4SAndroid Build Coastguard Worker {
109*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = cf->conn;
110*6236dae4SAndroid Build Coastguard Worker   curl_socket_t sock = conn->sock[cf->sockindex];
111*6236dae4SAndroid Build Coastguard Worker   CURLcode code;
112*6236dae4SAndroid Build Coastguard Worker   ssize_t actualread;
113*6236dae4SAndroid Build Coastguard Worker   ssize_t nwritten;
114*6236dae4SAndroid Build Coastguard Worker   int result;
115*6236dae4SAndroid Build Coastguard Worker   OM_uint32 gss_major_status, gss_minor_status, gss_status;
116*6236dae4SAndroid Build Coastguard Worker   OM_uint32 gss_ret_flags;
117*6236dae4SAndroid Build Coastguard Worker   int gss_conf_state, gss_enc;
118*6236dae4SAndroid Build Coastguard Worker   gss_buffer_desc  service = GSS_C_EMPTY_BUFFER;
119*6236dae4SAndroid Build Coastguard Worker   gss_buffer_desc  gss_send_token = GSS_C_EMPTY_BUFFER;
120*6236dae4SAndroid Build Coastguard Worker   gss_buffer_desc  gss_recv_token = GSS_C_EMPTY_BUFFER;
121*6236dae4SAndroid Build Coastguard Worker   gss_buffer_desc  gss_w_token = GSS_C_EMPTY_BUFFER;
122*6236dae4SAndroid Build Coastguard Worker   gss_buffer_desc *gss_token = GSS_C_NO_BUFFER;
123*6236dae4SAndroid Build Coastguard Worker   gss_name_t       server = GSS_C_NO_NAME;
124*6236dae4SAndroid Build Coastguard Worker   gss_name_t       gss_client_name = GSS_C_NO_NAME;
125*6236dae4SAndroid Build Coastguard Worker   unsigned short   us_length;
126*6236dae4SAndroid Build Coastguard Worker   char             *user = NULL;
127*6236dae4SAndroid Build Coastguard Worker   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
128*6236dae4SAndroid Build Coastguard Worker   const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
129*6236dae4SAndroid Build Coastguard Worker                            data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
130*6236dae4SAndroid Build Coastguard Worker   const size_t serviceptr_length = strlen(serviceptr);
131*6236dae4SAndroid Build Coastguard Worker 
132*6236dae4SAndroid Build Coastguard Worker   /*   GSS-API request looks like
133*6236dae4SAndroid Build Coastguard Worker    * +----+------+-----+----------------+
134*6236dae4SAndroid Build Coastguard Worker    * |VER | MTYP | LEN |     TOKEN      |
135*6236dae4SAndroid Build Coastguard Worker    * +----+------+----------------------+
136*6236dae4SAndroid Build Coastguard Worker    * | 1  |  1   |  2  | up to 2^16 - 1 |
137*6236dae4SAndroid Build Coastguard Worker    * +----+------+-----+----------------+
138*6236dae4SAndroid Build Coastguard Worker    */
139*6236dae4SAndroid Build Coastguard Worker 
140*6236dae4SAndroid Build Coastguard Worker   /* prepare service name */
141*6236dae4SAndroid Build Coastguard Worker   if(strchr(serviceptr, '/')) {
142*6236dae4SAndroid Build Coastguard Worker     service.length = serviceptr_length;
143*6236dae4SAndroid Build Coastguard Worker     service.value = Curl_memdup(serviceptr, service.length);
144*6236dae4SAndroid Build Coastguard Worker     if(!service.value)
145*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
146*6236dae4SAndroid Build Coastguard Worker 
147*6236dae4SAndroid Build Coastguard Worker     gss_major_status = gss_import_name(&gss_minor_status, &service,
148*6236dae4SAndroid Build Coastguard Worker                                        (gss_OID) GSS_C_NULL_OID, &server);
149*6236dae4SAndroid Build Coastguard Worker   }
150*6236dae4SAndroid Build Coastguard Worker   else {
151*6236dae4SAndroid Build Coastguard Worker     service.value = malloc(serviceptr_length +
152*6236dae4SAndroid Build Coastguard Worker                            strlen(conn->socks_proxy.host.name) + 2);
153*6236dae4SAndroid Build Coastguard Worker     if(!service.value)
154*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
155*6236dae4SAndroid Build Coastguard Worker     service.length = serviceptr_length +
156*6236dae4SAndroid Build Coastguard Worker       strlen(conn->socks_proxy.host.name) + 1;
157*6236dae4SAndroid Build Coastguard Worker     msnprintf(service.value, service.length + 1, "%s@%s",
158*6236dae4SAndroid Build Coastguard Worker               serviceptr, conn->socks_proxy.host.name);
159*6236dae4SAndroid Build Coastguard Worker 
160*6236dae4SAndroid Build Coastguard Worker     gss_major_status = gss_import_name(&gss_minor_status, &service,
161*6236dae4SAndroid Build Coastguard Worker                                        GSS_C_NT_HOSTBASED_SERVICE, &server);
162*6236dae4SAndroid Build Coastguard Worker   }
163*6236dae4SAndroid Build Coastguard Worker 
164*6236dae4SAndroid Build Coastguard Worker   gss_release_buffer(&gss_status, &service); /* clear allocated memory */
165*6236dae4SAndroid Build Coastguard Worker 
166*6236dae4SAndroid Build Coastguard Worker   if(check_gss_err(data, gss_major_status,
167*6236dae4SAndroid Build Coastguard Worker                    gss_minor_status, "gss_import_name()")) {
168*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to create service name.");
169*6236dae4SAndroid Build Coastguard Worker     gss_release_name(&gss_status, &server);
170*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
171*6236dae4SAndroid Build Coastguard Worker   }
172*6236dae4SAndroid Build Coastguard Worker 
173*6236dae4SAndroid Build Coastguard Worker   (void)curlx_nonblock(sock, FALSE);
174*6236dae4SAndroid Build Coastguard Worker 
175*6236dae4SAndroid Build Coastguard Worker   /* As long as we need to keep sending some context info, and there is no  */
176*6236dae4SAndroid Build Coastguard Worker   /* errors, keep sending it...                                            */
177*6236dae4SAndroid Build Coastguard Worker   for(;;) {
178*6236dae4SAndroid Build Coastguard Worker     gss_major_status = Curl_gss_init_sec_context(data,
179*6236dae4SAndroid Build Coastguard Worker                                                  &gss_minor_status,
180*6236dae4SAndroid Build Coastguard Worker                                                  &gss_context,
181*6236dae4SAndroid Build Coastguard Worker                                                  server,
182*6236dae4SAndroid Build Coastguard Worker                                                  &Curl_krb5_mech_oid,
183*6236dae4SAndroid Build Coastguard Worker                                                  NULL,
184*6236dae4SAndroid Build Coastguard Worker                                                  gss_token,
185*6236dae4SAndroid Build Coastguard Worker                                                  &gss_send_token,
186*6236dae4SAndroid Build Coastguard Worker                                                  TRUE,
187*6236dae4SAndroid Build Coastguard Worker                                                  &gss_ret_flags);
188*6236dae4SAndroid Build Coastguard Worker 
189*6236dae4SAndroid Build Coastguard Worker     if(gss_token != GSS_C_NO_BUFFER)
190*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_recv_token);
191*6236dae4SAndroid Build Coastguard Worker     if(check_gss_err(data, gss_major_status,
192*6236dae4SAndroid Build Coastguard Worker                      gss_minor_status, "gss_init_sec_context")) {
193*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
194*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_recv_token);
195*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_send_token);
196*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
197*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to initial GSS-API token.");
198*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
199*6236dae4SAndroid Build Coastguard Worker     }
200*6236dae4SAndroid Build Coastguard Worker 
201*6236dae4SAndroid Build Coastguard Worker     if(gss_send_token.length) {
202*6236dae4SAndroid Build Coastguard Worker       socksreq[0] = 1;    /* GSS-API subnegotiation version */
203*6236dae4SAndroid Build Coastguard Worker       socksreq[1] = 1;    /* authentication message type */
204*6236dae4SAndroid Build Coastguard Worker       us_length = htons((unsigned short)gss_send_token.length);
205*6236dae4SAndroid Build Coastguard Worker       memcpy(socksreq + 2, &us_length, sizeof(short));
206*6236dae4SAndroid Build Coastguard Worker 
207*6236dae4SAndroid Build Coastguard Worker       nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4,
208*6236dae4SAndroid Build Coastguard Worker                                    FALSE, &code);
209*6236dae4SAndroid Build Coastguard Worker       if(code || (4 != nwritten)) {
210*6236dae4SAndroid Build Coastguard Worker         failf(data, "Failed to send GSS-API authentication request.");
211*6236dae4SAndroid Build Coastguard Worker         gss_release_name(&gss_status, &server);
212*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&gss_status, &gss_recv_token);
213*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&gss_status, &gss_send_token);
214*6236dae4SAndroid Build Coastguard Worker         gss_delete_sec_context(&gss_status, &gss_context, NULL);
215*6236dae4SAndroid Build Coastguard Worker         return CURLE_COULDNT_CONNECT;
216*6236dae4SAndroid Build Coastguard Worker       }
217*6236dae4SAndroid Build Coastguard Worker 
218*6236dae4SAndroid Build Coastguard Worker       nwritten = Curl_conn_cf_send(cf->next, data,
219*6236dae4SAndroid Build Coastguard Worker                                    (char *)gss_send_token.value,
220*6236dae4SAndroid Build Coastguard Worker                                    gss_send_token.length, FALSE, &code);
221*6236dae4SAndroid Build Coastguard Worker       if(code || ((ssize_t)gss_send_token.length != nwritten)) {
222*6236dae4SAndroid Build Coastguard Worker         failf(data, "Failed to send GSS-API authentication token.");
223*6236dae4SAndroid Build Coastguard Worker         gss_release_name(&gss_status, &server);
224*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&gss_status, &gss_recv_token);
225*6236dae4SAndroid Build Coastguard Worker         gss_release_buffer(&gss_status, &gss_send_token);
226*6236dae4SAndroid Build Coastguard Worker         gss_delete_sec_context(&gss_status, &gss_context, NULL);
227*6236dae4SAndroid Build Coastguard Worker         return CURLE_COULDNT_CONNECT;
228*6236dae4SAndroid Build Coastguard Worker       }
229*6236dae4SAndroid Build Coastguard Worker 
230*6236dae4SAndroid Build Coastguard Worker     }
231*6236dae4SAndroid Build Coastguard Worker 
232*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_send_token);
233*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_recv_token);
234*6236dae4SAndroid Build Coastguard Worker     if(gss_major_status != GSS_S_CONTINUE_NEEDED)
235*6236dae4SAndroid Build Coastguard Worker       break;
236*6236dae4SAndroid Build Coastguard Worker 
237*6236dae4SAndroid Build Coastguard Worker     /* analyse response */
238*6236dae4SAndroid Build Coastguard Worker 
239*6236dae4SAndroid Build Coastguard Worker     /*   GSS-API response looks like
240*6236dae4SAndroid Build Coastguard Worker      * +----+------+-----+----------------+
241*6236dae4SAndroid Build Coastguard Worker      * |VER | MTYP | LEN |     TOKEN      |
242*6236dae4SAndroid Build Coastguard Worker      * +----+------+----------------------+
243*6236dae4SAndroid Build Coastguard Worker      * | 1  |  1   |  2  | up to 2^16 - 1 |
244*6236dae4SAndroid Build Coastguard Worker      * +----+------+-----+----------------+
245*6236dae4SAndroid Build Coastguard Worker      */
246*6236dae4SAndroid Build Coastguard Worker 
247*6236dae4SAndroid Build Coastguard Worker     result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
248*6236dae4SAndroid Build Coastguard Worker     if(result || (actualread != 4)) {
249*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to receive GSS-API authentication response.");
250*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
251*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
252*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
253*6236dae4SAndroid Build Coastguard Worker     }
254*6236dae4SAndroid Build Coastguard Worker 
255*6236dae4SAndroid Build Coastguard Worker     /* ignore the first (VER) byte */
256*6236dae4SAndroid Build Coastguard Worker     if(socksreq[1] == 255) { /* status / message type */
257*6236dae4SAndroid Build Coastguard Worker       failf(data, "User was rejected by the SOCKS5 server (%d %d).",
258*6236dae4SAndroid Build Coastguard Worker             socksreq[0], socksreq[1]);
259*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
260*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
261*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
262*6236dae4SAndroid Build Coastguard Worker     }
263*6236dae4SAndroid Build Coastguard Worker 
264*6236dae4SAndroid Build Coastguard Worker     if(socksreq[1] != 1) { /* status / message type */
265*6236dae4SAndroid Build Coastguard Worker       failf(data, "Invalid GSS-API authentication response type (%d %d).",
266*6236dae4SAndroid Build Coastguard Worker             socksreq[0], socksreq[1]);
267*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
268*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
269*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
270*6236dae4SAndroid Build Coastguard Worker     }
271*6236dae4SAndroid Build Coastguard Worker 
272*6236dae4SAndroid Build Coastguard Worker     memcpy(&us_length, socksreq + 2, sizeof(short));
273*6236dae4SAndroid Build Coastguard Worker     us_length = ntohs(us_length);
274*6236dae4SAndroid Build Coastguard Worker 
275*6236dae4SAndroid Build Coastguard Worker     gss_recv_token.length = us_length;
276*6236dae4SAndroid Build Coastguard Worker     gss_recv_token.value = malloc(us_length);
277*6236dae4SAndroid Build Coastguard Worker     if(!gss_recv_token.value) {
278*6236dae4SAndroid Build Coastguard Worker       failf(data,
279*6236dae4SAndroid Build Coastguard Worker             "Could not allocate memory for GSS-API authentication "
280*6236dae4SAndroid Build Coastguard Worker             "response token.");
281*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
282*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
283*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
284*6236dae4SAndroid Build Coastguard Worker     }
285*6236dae4SAndroid Build Coastguard Worker 
286*6236dae4SAndroid Build Coastguard Worker     result = Curl_blockread_all(cf, data, (char *)gss_recv_token.value,
287*6236dae4SAndroid Build Coastguard Worker                                 gss_recv_token.length, &actualread);
288*6236dae4SAndroid Build Coastguard Worker 
289*6236dae4SAndroid Build Coastguard Worker     if(result || (actualread != us_length)) {
290*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to receive GSS-API authentication token.");
291*6236dae4SAndroid Build Coastguard Worker       gss_release_name(&gss_status, &server);
292*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_recv_token);
293*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
294*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
295*6236dae4SAndroid Build Coastguard Worker     }
296*6236dae4SAndroid Build Coastguard Worker 
297*6236dae4SAndroid Build Coastguard Worker     gss_token = &gss_recv_token;
298*6236dae4SAndroid Build Coastguard Worker   }
299*6236dae4SAndroid Build Coastguard Worker 
300*6236dae4SAndroid Build Coastguard Worker   gss_release_name(&gss_status, &server);
301*6236dae4SAndroid Build Coastguard Worker 
302*6236dae4SAndroid Build Coastguard Worker   /* Everything is good so far, user was authenticated! */
303*6236dae4SAndroid Build Coastguard Worker   gss_major_status = gss_inquire_context(&gss_minor_status, gss_context,
304*6236dae4SAndroid Build Coastguard Worker                                          &gss_client_name, NULL, NULL, NULL,
305*6236dae4SAndroid Build Coastguard Worker                                          NULL, NULL, NULL);
306*6236dae4SAndroid Build Coastguard Worker   if(check_gss_err(data, gss_major_status,
307*6236dae4SAndroid Build Coastguard Worker                    gss_minor_status, "gss_inquire_context")) {
308*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
309*6236dae4SAndroid Build Coastguard Worker     gss_release_name(&gss_status, &gss_client_name);
310*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to determine username.");
311*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
312*6236dae4SAndroid Build Coastguard Worker   }
313*6236dae4SAndroid Build Coastguard Worker   gss_major_status = gss_display_name(&gss_minor_status, gss_client_name,
314*6236dae4SAndroid Build Coastguard Worker                                       &gss_send_token, NULL);
315*6236dae4SAndroid Build Coastguard Worker   if(check_gss_err(data, gss_major_status,
316*6236dae4SAndroid Build Coastguard Worker                    gss_minor_status, "gss_display_name")) {
317*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
318*6236dae4SAndroid Build Coastguard Worker     gss_release_name(&gss_status, &gss_client_name);
319*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_send_token);
320*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to determine username.");
321*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
322*6236dae4SAndroid Build Coastguard Worker   }
323*6236dae4SAndroid Build Coastguard Worker   user = malloc(gss_send_token.length + 1);
324*6236dae4SAndroid Build Coastguard Worker   if(!user) {
325*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
326*6236dae4SAndroid Build Coastguard Worker     gss_release_name(&gss_status, &gss_client_name);
327*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_send_token);
328*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
329*6236dae4SAndroid Build Coastguard Worker   }
330*6236dae4SAndroid Build Coastguard Worker 
331*6236dae4SAndroid Build Coastguard Worker   memcpy(user, gss_send_token.value, gss_send_token.length);
332*6236dae4SAndroid Build Coastguard Worker   user[gss_send_token.length] = '\0';
333*6236dae4SAndroid Build Coastguard Worker   gss_release_name(&gss_status, &gss_client_name);
334*6236dae4SAndroid Build Coastguard Worker   gss_release_buffer(&gss_status, &gss_send_token);
335*6236dae4SAndroid Build Coastguard Worker   infof(data, "SOCKS5 server authenticated user %s with GSS-API.",user);
336*6236dae4SAndroid Build Coastguard Worker   free(user);
337*6236dae4SAndroid Build Coastguard Worker   user = NULL;
338*6236dae4SAndroid Build Coastguard Worker 
339*6236dae4SAndroid Build Coastguard Worker   /* Do encryption */
340*6236dae4SAndroid Build Coastguard Worker   socksreq[0] = 1;    /* GSS-API subnegotiation version */
341*6236dae4SAndroid Build Coastguard Worker   socksreq[1] = 2;    /* encryption message type */
342*6236dae4SAndroid Build Coastguard Worker 
343*6236dae4SAndroid Build Coastguard Worker   gss_enc = 0; /* no data protection */
344*6236dae4SAndroid Build Coastguard Worker   /* do confidentiality protection if supported */
345*6236dae4SAndroid Build Coastguard Worker   if(gss_ret_flags & GSS_C_CONF_FLAG)
346*6236dae4SAndroid Build Coastguard Worker     gss_enc = 2;
347*6236dae4SAndroid Build Coastguard Worker   /* else do integrity protection */
348*6236dae4SAndroid Build Coastguard Worker   else if(gss_ret_flags & GSS_C_INTEG_FLAG)
349*6236dae4SAndroid Build Coastguard Worker     gss_enc = 1;
350*6236dae4SAndroid Build Coastguard Worker 
351*6236dae4SAndroid Build Coastguard Worker   infof(data, "SOCKS5 server supports GSS-API %s data protection.",
352*6236dae4SAndroid Build Coastguard Worker         (gss_enc == 0) ? "no" :
353*6236dae4SAndroid Build Coastguard Worker         ((gss_enc == 1) ? "integrity" : "confidentiality"));
354*6236dae4SAndroid Build Coastguard Worker   /* force for the moment to no data protection */
355*6236dae4SAndroid Build Coastguard Worker   gss_enc = 0;
356*6236dae4SAndroid Build Coastguard Worker   /*
357*6236dae4SAndroid Build Coastguard Worker    * Sending the encryption type in clear seems wrong. It should be
358*6236dae4SAndroid Build Coastguard Worker    * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
359*6236dae4SAndroid Build Coastguard Worker    * The NEC reference implementations on which this is based is
360*6236dae4SAndroid Build Coastguard Worker    * therefore at fault
361*6236dae4SAndroid Build Coastguard Worker    *
362*6236dae4SAndroid Build Coastguard Worker    *  +------+------+------+.......................+
363*6236dae4SAndroid Build Coastguard Worker    *  + ver  | mtyp | len  |   token               |
364*6236dae4SAndroid Build Coastguard Worker    *  +------+------+------+.......................+
365*6236dae4SAndroid Build Coastguard Worker    *  + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
366*6236dae4SAndroid Build Coastguard Worker    *  +------+------+------+.......................+
367*6236dae4SAndroid Build Coastguard Worker    *
368*6236dae4SAndroid Build Coastguard Worker    *   Where:
369*6236dae4SAndroid Build Coastguard Worker    *
370*6236dae4SAndroid Build Coastguard Worker    *  - "ver" is the protocol version number, here 1 to represent the
371*6236dae4SAndroid Build Coastguard Worker    *    first version of the SOCKS/GSS-API protocol
372*6236dae4SAndroid Build Coastguard Worker    *
373*6236dae4SAndroid Build Coastguard Worker    *  - "mtyp" is the message type, here 2 to represent a protection
374*6236dae4SAndroid Build Coastguard Worker    *    -level negotiation message
375*6236dae4SAndroid Build Coastguard Worker    *
376*6236dae4SAndroid Build Coastguard Worker    *  - "len" is the length of the "token" field in octets
377*6236dae4SAndroid Build Coastguard Worker    *
378*6236dae4SAndroid Build Coastguard Worker    *  - "token" is the GSS-API encapsulated protection level
379*6236dae4SAndroid Build Coastguard Worker    *
380*6236dae4SAndroid Build Coastguard Worker    * The token is produced by encapsulating an octet containing the
381*6236dae4SAndroid Build Coastguard Worker    * required protection level using gss_seal()/gss_wrap() with conf_req
382*6236dae4SAndroid Build Coastguard Worker    * set to FALSE. The token is verified using gss_unseal()/
383*6236dae4SAndroid Build Coastguard Worker    * gss_unwrap().
384*6236dae4SAndroid Build Coastguard Worker    *
385*6236dae4SAndroid Build Coastguard Worker    */
386*6236dae4SAndroid Build Coastguard Worker   if(data->set.socks5_gssapi_nec) {
387*6236dae4SAndroid Build Coastguard Worker     us_length = htons((short)1);
388*6236dae4SAndroid Build Coastguard Worker     memcpy(socksreq + 2, &us_length, sizeof(short));
389*6236dae4SAndroid Build Coastguard Worker   }
390*6236dae4SAndroid Build Coastguard Worker   else {
391*6236dae4SAndroid Build Coastguard Worker     gss_send_token.length = 1;
392*6236dae4SAndroid Build Coastguard Worker     gss_send_token.value = Curl_memdup(&gss_enc, 1);
393*6236dae4SAndroid Build Coastguard Worker     if(!gss_send_token.value) {
394*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
395*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
396*6236dae4SAndroid Build Coastguard Worker     }
397*6236dae4SAndroid Build Coastguard Worker 
398*6236dae4SAndroid Build Coastguard Worker     gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
399*6236dae4SAndroid Build Coastguard Worker                                 GSS_C_QOP_DEFAULT, &gss_send_token,
400*6236dae4SAndroid Build Coastguard Worker                                 &gss_conf_state, &gss_w_token);
401*6236dae4SAndroid Build Coastguard Worker 
402*6236dae4SAndroid Build Coastguard Worker     if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) {
403*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_send_token);
404*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_w_token);
405*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
406*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to wrap GSS-API encryption value into token.");
407*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
408*6236dae4SAndroid Build Coastguard Worker     }
409*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_send_token);
410*6236dae4SAndroid Build Coastguard Worker 
411*6236dae4SAndroid Build Coastguard Worker     us_length = htons((unsigned short)gss_w_token.length);
412*6236dae4SAndroid Build Coastguard Worker     memcpy(socksreq + 2, &us_length, sizeof(short));
413*6236dae4SAndroid Build Coastguard Worker   }
414*6236dae4SAndroid Build Coastguard Worker 
415*6236dae4SAndroid Build Coastguard Worker   nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
416*6236dae4SAndroid Build Coastguard Worker                                &code);
417*6236dae4SAndroid Build Coastguard Worker   if(code  || (4 != nwritten)) {
418*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to send GSS-API encryption request.");
419*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_w_token);
420*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
421*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
422*6236dae4SAndroid Build Coastguard Worker   }
423*6236dae4SAndroid Build Coastguard Worker 
424*6236dae4SAndroid Build Coastguard Worker   if(data->set.socks5_gssapi_nec) {
425*6236dae4SAndroid Build Coastguard Worker     memcpy(socksreq, &gss_enc, 1);
426*6236dae4SAndroid Build Coastguard Worker     nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
427*6236dae4SAndroid Build Coastguard Worker                                  &code);
428*6236dae4SAndroid Build Coastguard Worker     if(code || ( 1 != nwritten)) {
429*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to send GSS-API encryption type.");
430*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
431*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
432*6236dae4SAndroid Build Coastguard Worker     }
433*6236dae4SAndroid Build Coastguard Worker   }
434*6236dae4SAndroid Build Coastguard Worker   else {
435*6236dae4SAndroid Build Coastguard Worker     nwritten = Curl_conn_cf_send(cf->next, data,
436*6236dae4SAndroid Build Coastguard Worker                                  (char *)gss_w_token.value,
437*6236dae4SAndroid Build Coastguard Worker                                  gss_w_token.length, FALSE, &code);
438*6236dae4SAndroid Build Coastguard Worker     if(code || ((ssize_t)gss_w_token.length != nwritten)) {
439*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to send GSS-API encryption type.");
440*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_w_token);
441*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
442*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
443*6236dae4SAndroid Build Coastguard Worker     }
444*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_w_token);
445*6236dae4SAndroid Build Coastguard Worker   }
446*6236dae4SAndroid Build Coastguard Worker 
447*6236dae4SAndroid Build Coastguard Worker   result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
448*6236dae4SAndroid Build Coastguard Worker   if(result || (actualread != 4)) {
449*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to receive GSS-API encryption response.");
450*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
451*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
452*6236dae4SAndroid Build Coastguard Worker   }
453*6236dae4SAndroid Build Coastguard Worker 
454*6236dae4SAndroid Build Coastguard Worker   /* ignore the first (VER) byte */
455*6236dae4SAndroid Build Coastguard Worker   if(socksreq[1] == 255) { /* status / message type */
456*6236dae4SAndroid Build Coastguard Worker     failf(data, "User was rejected by the SOCKS5 server (%d %d).",
457*6236dae4SAndroid Build Coastguard Worker           socksreq[0], socksreq[1]);
458*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
459*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
460*6236dae4SAndroid Build Coastguard Worker   }
461*6236dae4SAndroid Build Coastguard Worker 
462*6236dae4SAndroid Build Coastguard Worker   if(socksreq[1] != 2) { /* status / message type */
463*6236dae4SAndroid Build Coastguard Worker     failf(data, "Invalid GSS-API encryption response type (%d %d).",
464*6236dae4SAndroid Build Coastguard Worker           socksreq[0], socksreq[1]);
465*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
466*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
467*6236dae4SAndroid Build Coastguard Worker   }
468*6236dae4SAndroid Build Coastguard Worker 
469*6236dae4SAndroid Build Coastguard Worker   memcpy(&us_length, socksreq + 2, sizeof(short));
470*6236dae4SAndroid Build Coastguard Worker   us_length = ntohs(us_length);
471*6236dae4SAndroid Build Coastguard Worker 
472*6236dae4SAndroid Build Coastguard Worker   gss_recv_token.length = us_length;
473*6236dae4SAndroid Build Coastguard Worker   gss_recv_token.value = malloc(gss_recv_token.length);
474*6236dae4SAndroid Build Coastguard Worker   if(!gss_recv_token.value) {
475*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
476*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
477*6236dae4SAndroid Build Coastguard Worker   }
478*6236dae4SAndroid Build Coastguard Worker   result = Curl_blockread_all(cf, data, (char *)gss_recv_token.value,
479*6236dae4SAndroid Build Coastguard Worker                               gss_recv_token.length, &actualread);
480*6236dae4SAndroid Build Coastguard Worker 
481*6236dae4SAndroid Build Coastguard Worker   if(result || (actualread != us_length)) {
482*6236dae4SAndroid Build Coastguard Worker     failf(data, "Failed to receive GSS-API encryption type.");
483*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_recv_token);
484*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
485*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
486*6236dae4SAndroid Build Coastguard Worker   }
487*6236dae4SAndroid Build Coastguard Worker 
488*6236dae4SAndroid Build Coastguard Worker   if(!data->set.socks5_gssapi_nec) {
489*6236dae4SAndroid Build Coastguard Worker     gss_major_status = gss_unwrap(&gss_minor_status, gss_context,
490*6236dae4SAndroid Build Coastguard Worker                                   &gss_recv_token, &gss_w_token,
491*6236dae4SAndroid Build Coastguard Worker                                   0, GSS_C_QOP_DEFAULT);
492*6236dae4SAndroid Build Coastguard Worker 
493*6236dae4SAndroid Build Coastguard Worker     if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) {
494*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_recv_token);
495*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_w_token);
496*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
497*6236dae4SAndroid Build Coastguard Worker       failf(data, "Failed to unwrap GSS-API encryption value into token.");
498*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
499*6236dae4SAndroid Build Coastguard Worker     }
500*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_recv_token);
501*6236dae4SAndroid Build Coastguard Worker 
502*6236dae4SAndroid Build Coastguard Worker     if(gss_w_token.length != 1) {
503*6236dae4SAndroid Build Coastguard Worker       failf(data, "Invalid GSS-API encryption response length (%zu).",
504*6236dae4SAndroid Build Coastguard Worker             gss_w_token.length);
505*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_w_token);
506*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
507*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
508*6236dae4SAndroid Build Coastguard Worker     }
509*6236dae4SAndroid Build Coastguard Worker 
510*6236dae4SAndroid Build Coastguard Worker     memcpy(socksreq, gss_w_token.value, gss_w_token.length);
511*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_w_token);
512*6236dae4SAndroid Build Coastguard Worker   }
513*6236dae4SAndroid Build Coastguard Worker   else {
514*6236dae4SAndroid Build Coastguard Worker     if(gss_recv_token.length != 1) {
515*6236dae4SAndroid Build Coastguard Worker       failf(data, "Invalid GSS-API encryption response length (%zu).",
516*6236dae4SAndroid Build Coastguard Worker             gss_recv_token.length);
517*6236dae4SAndroid Build Coastguard Worker       gss_release_buffer(&gss_status, &gss_recv_token);
518*6236dae4SAndroid Build Coastguard Worker       gss_delete_sec_context(&gss_status, &gss_context, NULL);
519*6236dae4SAndroid Build Coastguard Worker       return CURLE_COULDNT_CONNECT;
520*6236dae4SAndroid Build Coastguard Worker     }
521*6236dae4SAndroid Build Coastguard Worker 
522*6236dae4SAndroid Build Coastguard Worker     memcpy(socksreq, gss_recv_token.value, gss_recv_token.length);
523*6236dae4SAndroid Build Coastguard Worker     gss_release_buffer(&gss_status, &gss_recv_token);
524*6236dae4SAndroid Build Coastguard Worker   }
525*6236dae4SAndroid Build Coastguard Worker 
526*6236dae4SAndroid Build Coastguard Worker   (void)curlx_nonblock(sock, TRUE);
527*6236dae4SAndroid Build Coastguard Worker 
528*6236dae4SAndroid Build Coastguard Worker   infof(data, "SOCKS5 access with%s protection granted.",
529*6236dae4SAndroid Build Coastguard Worker         (socksreq[0] == 0) ? "out GSS-API data":
530*6236dae4SAndroid Build Coastguard Worker         ((socksreq[0] == 1) ? " GSS-API integrity" :
531*6236dae4SAndroid Build Coastguard Worker          " GSS-API confidentiality"));
532*6236dae4SAndroid Build Coastguard Worker 
533*6236dae4SAndroid Build Coastguard Worker   conn->socks5_gssapi_enctype = socksreq[0];
534*6236dae4SAndroid Build Coastguard Worker   if(socksreq[0] == 0)
535*6236dae4SAndroid Build Coastguard Worker     gss_delete_sec_context(&gss_status, &gss_context, NULL);
536*6236dae4SAndroid Build Coastguard Worker 
537*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
538*6236dae4SAndroid Build Coastguard Worker }
539*6236dae4SAndroid Build Coastguard Worker 
540*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */
541