1 /** @file
2 
3   A brief file description
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 /*
25   Socks.cc
26 
27 
28 
29   This file contains the Socks client functionality. Previously this code was
30   duplicated in UnixNet.cc and NTNetProcessor.cc
31 */
32 
33 #include "P_Net.h"
34 #include "tscore/I_Layout.h"
35 #include "tscore/ink_sock.h"
36 #include "tscore/InkErrno.h"
37 #include "tscore/IpMapConf.h"
38 
39 socks_conf_struct *g_socks_conf_stuff = nullptr;
40 
41 ClassAllocator<SocksEntry> socksAllocator("socksAllocator");
42 
43 void
init(Ptr<ProxyMutex> & m,SocksNetVC * vc,unsigned char socks_support,unsigned char ver)44 SocksEntry::init(Ptr<ProxyMutex> &m, SocksNetVC *vc, unsigned char socks_support, unsigned char ver)
45 {
46   mutex  = m;
47   buf    = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
48   reader = buf->alloc_reader();
49 
50   socks_cmd = socks_support;
51 
52   if (ver == SOCKS_DEFAULT_VERSION) {
53     version = netProcessor.socks_conf_stuff->default_version;
54   } else {
55     version = ver;
56   }
57 
58   SET_HANDLER(&SocksEntry::startEvent);
59 
60   ats_ip_copy(&target_addr, vc->get_remote_addr());
61 
62 #ifdef SOCKS_WITH_TS
63   req_data.hdr          = nullptr;
64   req_data.hostname_str = nullptr;
65   req_data.api_info     = nullptr;
66   req_data.xact_start   = time(nullptr);
67 
68   assert(ats_is_ip4(&target_addr));
69   ats_ip_copy(&req_data.dest_ip, &target_addr);
70 
71   // we dont have information about the source. set to destination's
72   ats_ip_copy(&req_data.src_ip, &target_addr);
73 
74   server_params = SocksServerConfig::acquire();
75 #endif
76 
77   nattempts = 0;
78   findServer();
79 
80   timeout    = this_ethread()->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->server_connect_timeout));
81   write_done = false;
82 }
83 
84 void
findServer()85 SocksEntry::findServer()
86 {
87   nattempts++;
88   unsigned int fail_threshold = server_params->policy.FailThreshold;
89   unsigned int retry_time     = server_params->policy.ParentRetryTime;
90 
91 #ifdef SOCKS_WITH_TS
92   if (nattempts == 1) {
93     ink_assert(server_result.result == PARENT_UNDEFINED);
94     server_params->findParent(&req_data, &server_result, fail_threshold, retry_time);
95   } else {
96     socks_conf_struct *conf = netProcessor.socks_conf_stuff;
97     if ((nattempts - 1) % conf->per_server_connection_attempts) {
98       return; // attempt again
99     }
100 
101     server_params->markParentDown(&server_result, fail_threshold, retry_time);
102 
103     if (nattempts > conf->connection_attempts) {
104       server_result.result = PARENT_FAIL;
105     } else {
106       server_params->nextParent(&req_data, &server_result, fail_threshold, retry_time);
107     }
108   }
109 
110   switch (server_result.result) {
111   case PARENT_SPECIFIED:
112     // Original was inet_addr, but should hostnames work?
113     // ats_ip_pton only supports numeric (because other clients
114     // explicitly want to avoid hostname lookups).
115     if (0 == ats_ip_pton(server_result.hostname, &server_addr)) {
116       ats_ip_port_cast(&server_addr) = htons(server_result.port);
117     } else {
118       Debug("SocksParent", "Invalid parent server specified %s", server_result.hostname);
119     }
120     break;
121 
122   default:
123     ink_assert(!"Unexpected event");
124   // fallthrough
125   case PARENT_DIRECT:
126   case PARENT_FAIL:
127     memset(&server_addr, 0, sizeof(server_addr));
128   }
129 #else
130   if (nattempts > netProcessor.socks_conf_stuff->connection_attempts)
131     memset(&server_addr, 0, sizeof(server_addr));
132   else
133     ats_ip_copy(&server_addr, &g_socks_conf_stuff->server_addr);
134 #endif // SOCKS_WITH_TS
135 
136   char buff[INET6_ADDRSTRLEN];
137   Debug("SocksParents", "findServer result: %s:%d", ats_ip_ntop(&server_addr.sa, buff, sizeof(buff)),
138         ats_ip_port_host_order(&server_addr));
139 }
140 
141 void
free()142 SocksEntry::free()
143 {
144   MUTEX_TRY_LOCK(lock, action_.mutex, this_ethread());
145   // Socks continuation share the user's lock
146   // so acquiring a lock shouldn't fail
147   ink_release_assert(lock.is_locked());
148 
149   if (timeout) {
150     timeout->cancel(this);
151   }
152 
153 #ifdef SOCKS_WITH_TS
154   if (!lerrno && netVConnection && server_result.retry) {
155     server_params->markParentUp(&server_result);
156   }
157 #endif
158 
159   if ((action_.cancelled || lerrno) && netVConnection) {
160     netVConnection->do_io_close();
161   }
162 
163   if (!action_.cancelled) {
164     if (lerrno || !netVConnection) {
165       Debug("Socks", "retryevent: Sent errno %d to HTTP", lerrno);
166       NET_INCREMENT_DYN_STAT(socks_connections_unsuccessful_stat);
167       action_.continuation->handleEvent(NET_EVENT_OPEN_FAILED, (void *)static_cast<intptr_t>(-lerrno));
168     } else {
169       netVConnection->do_io_read(this, 0, nullptr);
170       netVConnection->do_io_write(this, 0, nullptr);
171       netVConnection->action_ = action_; // assign the original continuation
172       netVConnection->con.setRemote(&server_addr.sa);
173       Debug("Socks", "Sent success to HTTP");
174       NET_INCREMENT_DYN_STAT(socks_connections_successful_stat);
175       action_.continuation->handleEvent(NET_EVENT_OPEN, netVConnection);
176     }
177   }
178 #ifdef SOCKS_WITH_TS
179   SocksServerConfig::release(server_params);
180 #endif
181 
182   free_MIOBuffer(buf);
183   action_ = nullptr;
184   mutex   = nullptr;
185   socksAllocator.free(this);
186 }
187 
188 int
startEvent(int event,void * data)189 SocksEntry::startEvent(int event, void *data)
190 {
191   if (event == NET_EVENT_OPEN) {
192     netVConnection = static_cast<SocksNetVC *>(data);
193 
194     if (version == SOCKS5_VERSION) {
195       auth_handler = &socks5BasicAuthHandler;
196     }
197 
198     SET_HANDLER((SocksEntryHandler)&SocksEntry::mainEvent);
199     mainEvent(NET_EVENT_OPEN, data);
200   } else {
201     if (timeout) {
202       timeout->cancel(this);
203       timeout = nullptr;
204     }
205 
206     char buff[INET6_ADDRPORTSTRLEN];
207     Debug("Socks", "Failed to connect to %s", ats_ip_nptop(&server_addr.sa, buff, sizeof(buff)));
208 
209     findServer();
210 
211     if (!ats_is_ip(&server_addr)) {
212       Debug("Socks", "Unable to open connection to the SOCKS server");
213       lerrno = ESOCK_NO_SOCK_SERVER_CONN;
214       free();
215       return EVENT_CONT;
216     }
217 
218     if (timeout) {
219       timeout->cancel(this);
220       timeout = nullptr;
221     }
222 
223     if (netVConnection) {
224       netVConnection->do_io_close();
225       netVConnection = nullptr;
226     }
227 
228     timeout = this_ethread()->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->server_connect_timeout));
229 
230     write_done = false;
231 
232     NetVCOptions options;
233     options.socks_support = NO_SOCKS;
234     netProcessor.connect_re(this, &server_addr.sa, &options);
235   }
236 
237   return EVENT_CONT;
238 }
239 
240 int
mainEvent(int event,void * data)241 SocksEntry::mainEvent(int event, void *data)
242 {
243   int ret     = EVENT_DONE;
244   int n_bytes = 0;
245   unsigned char *p;
246 
247   switch (event) {
248   case NET_EVENT_OPEN:
249     buf->reset();
250     unsigned short ts;
251     p = reinterpret_cast<unsigned char *>(buf->start());
252     ink_assert(netVConnection);
253 
254     if (auth_handler) {
255       n_bytes = invokeSocksAuthHandler(auth_handler, SOCKS_AUTH_OPEN, p);
256     } else {
257       // Debug("Socks", " Got NET_EVENT_OPEN to SOCKS server");
258 
259       p[n_bytes++] = version;
260       p[n_bytes++] = (socks_cmd == NORMAL_SOCKS) ? SOCKS_CONNECT : socks_cmd;
261       ts           = ats_ip_port_cast(&target_addr);
262 
263       if (version == SOCKS5_VERSION) {
264         p[n_bytes++] = 0; // Reserved
265         if (ats_is_ip4(&target_addr)) {
266           p[n_bytes++] = 1; // IPv4 addr
267           memcpy(p + n_bytes, &target_addr.sin.sin_addr, 4);
268           n_bytes += 4;
269         } else if (ats_is_ip6(&target_addr)) {
270           p[n_bytes++] = 4; // IPv6 addr
271           memcpy(p + n_bytes, &target_addr.sin6.sin6_addr, TS_IP6_SIZE);
272           n_bytes += TS_IP6_SIZE;
273         } else {
274           Debug("Socks", "SOCKS supports only IP addresses.");
275         }
276       }
277 
278       memcpy(p + n_bytes, &ts, 2);
279       n_bytes += 2;
280 
281       if (version == SOCKS4_VERSION) {
282         if (ats_is_ip4(&target_addr)) {
283           // for socks4, ip addr is after the port
284           memcpy(p + n_bytes, &target_addr.sin.sin_addr, 4);
285           n_bytes += 4;
286 
287           p[n_bytes++] = 0; // nullptr
288         } else {
289           Debug("Socks", "SOCKS v4 supports only IPv4 addresses.");
290         }
291       }
292     }
293 
294     buf->fill(n_bytes);
295 
296     if (!timeout) {
297       /* timeout would be already set when we come here from StartEvent() */
298       timeout = this_ethread()->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->socks_timeout));
299     }
300 
301     netVConnection->do_io_write(this, n_bytes, reader, false);
302     // Debug("Socks", "Sent the request to the SOCKS server");
303 
304     ret = EVENT_CONT;
305     break;
306 
307   case VC_EVENT_WRITE_READY:
308 
309     ret = EVENT_CONT;
310     break;
311 
312   case VC_EVENT_WRITE_COMPLETE:
313     if (timeout) {
314       timeout->cancel(this);
315       timeout    = nullptr;
316       write_done = true;
317     }
318 
319     buf->reset(); // Use the same buffer for a read now
320 
321     if (auth_handler) {
322       n_bytes = invokeSocksAuthHandler(auth_handler, SOCKS_AUTH_WRITE_COMPLETE, nullptr);
323     } else if (socks_cmd == NORMAL_SOCKS) {
324       n_bytes = (version == SOCKS5_VERSION) ? SOCKS5_REP_LEN : SOCKS4_REP_LEN;
325     } else {
326       Debug("Socks", "Tunnelling the connection");
327       // let the client handle the response
328       free();
329       break;
330     }
331 
332     timeout = this_ethread()->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->socks_timeout));
333 
334     netVConnection->do_io_read(this, n_bytes, buf);
335 
336     ret = EVENT_DONE;
337     break;
338 
339   case VC_EVENT_READ_READY:
340     ret = EVENT_CONT;
341 
342     if (version == SOCKS5_VERSION && auth_handler == nullptr) {
343       VIO *vio = static_cast<VIO *>(data);
344       p        = reinterpret_cast<unsigned char *>(buf->start());
345 
346       if (vio->ndone >= 5) {
347         int reply_len;
348 
349         switch (p[3]) {
350         case SOCKS_ATYPE_IPV4:
351           reply_len = 10;
352           break;
353         case SOCKS_ATYPE_FQHN:
354           reply_len = 7 + p[4];
355           break;
356         case SOCKS_ATYPE_IPV6:
357           Debug("Socks", "Who is using IPv6 Addr?");
358           reply_len = 22;
359           break;
360         default:
361           reply_len = INT_MAX;
362           Debug("Socks", "Illegal address type(%d) in Socks server", (int)p[3]);
363         }
364 
365         if (vio->ndone >= reply_len) {
366           vio->nbytes = vio->ndone;
367           ret         = EVENT_DONE;
368         }
369       }
370     }
371 
372     if (ret == EVENT_CONT) {
373       break;
374     }
375   // Fall Through
376   case VC_EVENT_READ_COMPLETE:
377     if (timeout) {
378       timeout->cancel(this);
379       timeout = nullptr;
380     }
381     // Debug("Socks", "Successfully read the reply from the SOCKS server");
382     p = reinterpret_cast<unsigned char *>(buf->start());
383 
384     if (auth_handler) {
385       SocksAuthHandler temp = auth_handler;
386 
387       if (invokeSocksAuthHandler(auth_handler, SOCKS_AUTH_READ_COMPLETE, p) < 0) {
388         lerrno = ESOCK_DENIED;
389         free();
390       } else if (auth_handler != temp) {
391         // here either authorization is done or there is another
392         // stage left.
393         mainEvent(NET_EVENT_OPEN, nullptr);
394       }
395 
396     } else {
397       bool success;
398       if (version == SOCKS5_VERSION) {
399         success = (p[0] == SOCKS5_VERSION && p[1] == SOCKS5_REQ_GRANTED);
400         Debug("Socks", "received reply of length %" PRId64 " addr type %d", ((VIO *)data)->ndone, (int)p[3]);
401       } else {
402         success = (p[0] == 0 && p[1] == SOCKS4_REQ_GRANTED);
403       }
404 
405       // ink_assert(*(p) == 0);
406       if (!success) { // SOCKS request failed
407         Debug("Socks", "Socks request denied %d", (int)*(p + 1));
408         lerrno = ESOCK_DENIED;
409       } else {
410         Debug("Socks", "Socks request successful %d", (int)*(p + 1));
411         lerrno = 0;
412       }
413       free();
414     }
415 
416     break;
417 
418   case EVENT_INTERVAL:
419     timeout = nullptr;
420     if (write_done) {
421       lerrno = ESOCK_TIMEOUT;
422       free();
423       break;
424     }
425     /* else
426        This is server_connect_timeout. So we treat this as server being
427        down.
428        Should cancel any pending connect() action. Important on windows
429     */
430     // fallthrough
431 
432   case VC_EVENT_ERROR:
433     /*This is mostly ECONNREFUSED on Unix */
434     SET_HANDLER(&SocksEntry::startEvent);
435     startEvent(NET_EVENT_OPEN_FAILED, nullptr);
436     break;
437 
438   case VC_EVENT_EOS:
439   case VC_EVENT_INACTIVITY_TIMEOUT:
440   case VC_EVENT_ACTIVE_TIMEOUT:
441     Debug("Socks", "VC_EVENT error: %s", get_vc_event_name(event));
442     lerrno = ESOCK_NO_SOCK_SERVER_CONN;
443     free();
444     break;
445   default:
446     // BUGBUG:: could be active/inactivity timeout ...
447     ink_assert(!"bad case value");
448     Debug("Socks", "Bad Case/Net Error Event");
449     lerrno = ESOCK_NO_SOCK_SERVER_CONN;
450     free();
451     break;
452   }
453 
454   return ret;
455 }
456 
457 void
loadSocksConfiguration(socks_conf_struct * socks_conf_stuff)458 loadSocksConfiguration(socks_conf_struct *socks_conf_stuff)
459 {
460   int socks_config_fd = -1;
461   ats_scoped_str config_pathname;
462 #ifdef SOCKS_WITH_TS
463   char *tmp;
464 #endif
465 
466   socks_conf_stuff->accept_enabled = 0; // initialize it INKqa08593
467   socks_conf_stuff->socks_needed   = REC_ConfigReadInteger("proxy.config.socks.socks_needed");
468   if (!socks_conf_stuff->socks_needed) {
469     Debug("Socks", "Socks Turned Off");
470     return;
471   }
472 
473   socks_conf_stuff->default_version = REC_ConfigReadInteger("proxy.config.socks.socks_version");
474   Debug("Socks", "Socks Version %d", socks_conf_stuff->default_version);
475 
476   if (socks_conf_stuff->default_version != 4 && socks_conf_stuff->default_version != 5) {
477     Error("SOCKS Config: Unsupported Version: %d. SOCKS Turned off", socks_conf_stuff->default_version);
478     goto error;
479   }
480 
481   socks_conf_stuff->server_connect_timeout = REC_ConfigReadInteger("proxy.config.socks.server_connect_timeout");
482   socks_conf_stuff->socks_timeout          = REC_ConfigReadInteger("proxy.config.socks.socks_timeout");
483   Debug("Socks", "server connect timeout: %d socks response timeout %d", socks_conf_stuff->server_connect_timeout,
484         socks_conf_stuff->socks_timeout);
485 
486   socks_conf_stuff->per_server_connection_attempts = REC_ConfigReadInteger("proxy.config.socks.per_server_connection_attempts");
487   socks_conf_stuff->connection_attempts            = REC_ConfigReadInteger("proxy.config.socks.connection_attempts");
488 
489   socks_conf_stuff->accept_enabled = REC_ConfigReadInteger("proxy.config.socks.accept_enabled");
490   socks_conf_stuff->accept_port    = REC_ConfigReadInteger("proxy.config.socks.accept_port");
491   socks_conf_stuff->http_port      = REC_ConfigReadInteger("proxy.config.socks.http_port");
492   Debug("SocksProxy",
493         "Read SocksProxy info: accept_enabled = %d "
494         "accept_port = %d http_port = %d",
495         socks_conf_stuff->accept_enabled, socks_conf_stuff->accept_port, socks_conf_stuff->http_port);
496 
497 #ifdef SOCKS_WITH_TS
498   SocksServerConfig::startup();
499 #endif
500 
501   config_pathname = RecConfigReadConfigPath("proxy.config.socks.socks_config_file");
502   Debug("Socks", "Socks Config File: %s", (const char *)config_pathname);
503 
504   if (!config_pathname) {
505     Error("SOCKS Config: could not read config file name. SOCKS Turned off");
506     goto error;
507   }
508 
509   socks_config_fd = ::open(config_pathname, O_RDONLY);
510 
511   if (socks_config_fd < 0) {
512     Error("SOCKS Config: could not open config file '%s'. SOCKS Turned off", (const char *)config_pathname);
513     goto error;
514   }
515 #ifdef SOCKS_WITH_TS
516   tmp = Load_IpMap_From_File(&socks_conf_stuff->ip_map, socks_config_fd, "no_socks");
517 
518   if (tmp) {
519     Error("SOCKS Config: Error while reading ip_range: %s.", tmp);
520     ats_free(tmp);
521     goto error;
522   }
523 #endif
524 
525   if (loadSocksAuthInfo(socks_config_fd, socks_conf_stuff) != 0) {
526     Error("SOCKS Config: Error while reading Socks auth info");
527     goto error;
528   }
529   Debug("Socks", "Socks Turned on");
530   ::close(socks_config_fd);
531 
532   return;
533 error:
534 
535   socks_conf_stuff->socks_needed   = 0;
536   socks_conf_stuff->accept_enabled = 0;
537   if (socks_config_fd >= 0) {
538     ::close(socks_config_fd);
539   }
540 }
541 
542 int
loadSocksAuthInfo(int fd,socks_conf_struct * socks_stuff)543 loadSocksAuthInfo(int fd, socks_conf_struct *socks_stuff)
544 {
545   char c              = '\0';
546   char line[256]      = {0}; // initialize all chars to nil
547   char user_name[256] = {0};
548   char passwd[256]    = {0};
549 
550   if (lseek(fd, 0, SEEK_SET) < 0) {
551     Warning("Can not seek on Socks configuration file\n");
552     return -1;
553   }
554 
555   bool end_of_file = false;
556   do {
557     int n = 0, rc;
558     while (((rc = read(fd, &c, 1)) == 1) && (c != '\n') && (n < 254)) {
559       line[n++] = c;
560     }
561     if (rc <= 0) {
562       end_of_file = true;
563     }
564     line[n] = '\0';
565 
566     // coverity[secure_coding]
567     rc = sscanf(line, " auth u %255s %255s ", user_name, passwd);
568     if (rc >= 2) {
569       int len1 = strlen(user_name);
570       int len2 = strlen(passwd);
571 
572       Debug("Socks", "Read user_name(%s) and passwd(%s) from config file", user_name, passwd);
573 
574       socks_stuff->user_name_n_passwd_len = len1 + len2 + 2;
575 
576       char *ptr = static_cast<char *>(ats_malloc(socks_stuff->user_name_n_passwd_len));
577       ptr[0]    = len1;
578       memcpy(&ptr[1], user_name, len1);
579       ptr[len1 + 1] = len2;
580       memcpy(&ptr[len1 + 2], passwd, len2);
581 
582       socks_stuff->user_name_n_passwd = ptr;
583 
584       return 0;
585     }
586   } while (!end_of_file);
587 
588   return 0;
589 }
590 
591 int
socks5BasicAuthHandler(int event,unsigned char * p,void (** h_ptr)(void))592 socks5BasicAuthHandler(int event, unsigned char *p, void (**h_ptr)(void))
593 {
594   // for more info on Socks5 see RFC 1928
595   int ret           = 0;
596   char *pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd;
597 
598   switch (event) {
599   case SOCKS_AUTH_OPEN:
600     p[ret++] = SOCKS5_VERSION;        // version
601     p[ret++] = (pass_phrase) ? 2 : 1; //#Methods
602     p[ret++] = 0;                     // no authentication
603     if (pass_phrase) {
604       p[ret++] = 2;
605     }
606 
607     break;
608 
609   case SOCKS_AUTH_WRITE_COMPLETE:
610     // return number of bytes to read
611     ret = 2;
612     break;
613 
614   case SOCKS_AUTH_READ_COMPLETE:
615 
616     if (p[0] == SOCKS5_VERSION) {
617       switch (p[1]) {
618       case 0: // no authentication required
619         Debug("Socks", "No authentication required for Socks server");
620         // make sure this is ok for us. right now it is always ok for us.
621         *h_ptr = nullptr;
622         break;
623 
624       case 2:
625         Debug("Socks", "Socks server wants username/passwd");
626         if (!pass_phrase) {
627           Debug("Socks", "Buggy Socks server: asks for username/passwd "
628                          "when not supplied as an option");
629           ret    = -1;
630           *h_ptr = nullptr;
631         } else {
632           *reinterpret_cast<SocksAuthHandler *>(h_ptr) = &socks5PasswdAuthHandler;
633         }
634 
635         break;
636 
637       case 0xff:
638         Debug("Socks", "None of the Socks authentications is acceptable "
639                        "to the server");
640         *h_ptr = nullptr;
641         ret    = -1;
642         break;
643 
644       default:
645         Debug("Socks", "Unexpected Socks auth method (%d) from the server", (int)p[1]);
646         ret = -1;
647         break;
648       }
649     } else {
650       Debug("Socks", "authEvent got wrong version %d from the Socks server", (int)p[0]);
651       ret = -1;
652     }
653 
654     break;
655 
656   default:
657     // This should be impossible
658     ink_assert(!"bad case value");
659     ret = -1;
660     break;
661   }
662   return ret;
663 }
664 
665 int
socks5PasswdAuthHandler(int event,unsigned char * p,void (** h_ptr)(void))666 socks5PasswdAuthHandler(int event, unsigned char *p, void (**h_ptr)(void))
667 {
668   // for more info see RFC 1929
669   int ret = 0;
670   char *pass_phrase;
671   int pass_len;
672 
673   switch (event) {
674   case SOCKS_AUTH_OPEN:
675     pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd;
676     pass_len    = netProcessor.socks_conf_stuff->user_name_n_passwd_len;
677     ink_assert(pass_phrase);
678 
679     p[0] = 1; // version
680     memcpy(&p[1], pass_phrase, pass_len);
681 
682     ret = 1 + pass_len;
683     break;
684 
685   case SOCKS_AUTH_WRITE_COMPLETE:
686     // return number of bytes to read
687     ret = 2;
688     break;
689 
690   case SOCKS_AUTH_READ_COMPLETE:
691     // NEC thinks it is 5 RFC seems to indicate 1.
692     switch (p[1]) {
693     case 0:
694       Debug("Socks", "Username/Passwd succeeded");
695       *h_ptr = nullptr;
696       break;
697 
698     default:
699       Debug("Socks", "Username/Passwd authentication failed ret_code: %d", (int)p[1]);
700       ret = -1;
701     }
702 
703     break;
704 
705   default:
706     ink_assert(!"bad case value");
707     ret = -1;
708     break;
709   }
710   return ret;
711 }
712