1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24/* This is the 'proxyauth.c' test app posted by Shmulik Regev on the libcurl 25 * mailing list on 10 Jul 2007, converted to a test case. 26 * 27 * argv1 = URL 28 * argv2 = proxy 29 * argv3 = proxyuser:password 30 * argv4 = host name to use for the custom Host: header 31 */ 32 33#include "test.h" 34 35#include <limits.h> 36 37#include "testutil.h" 38#include "warnless.h" 39#include "memdebug.h" 40 41#define TEST_HANG_TIMEOUT 60 * 1000 42 43#define PROXY libtest_arg2 44#define PROXYUSERPWD libtest_arg3 45#define HOST test_argv[4] 46 47#define NUM_HANDLES 2 48 49static CURL *eh[NUM_HANDLES]; 50 51static int init(int num, CURLM *cm, const char *url, const char *userpwd, 52 struct curl_slist *headers) 53{ 54 int res = 0; 55 56 res_easy_init(eh[num]); 57 if(res) 58 goto init_failed; 59 60 res_easy_setopt(eh[num], CURLOPT_URL, url); 61 if(res) 62 goto init_failed; 63 64 res_easy_setopt(eh[num], CURLOPT_PROXY, PROXY); 65 if(res) 66 goto init_failed; 67 68 res_easy_setopt(eh[num], CURLOPT_PROXYUSERPWD, userpwd); 69 if(res) 70 goto init_failed; 71 72 res_easy_setopt(eh[num], CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY); 73 if(res) 74 goto init_failed; 75 76 res_easy_setopt(eh[num], CURLOPT_VERBOSE, 1L); 77 if(res) 78 goto init_failed; 79 80 res_easy_setopt(eh[num], CURLOPT_HEADER, 1L); 81 if(res) 82 goto init_failed; 83 84 res_easy_setopt(eh[num], CURLOPT_HTTPHEADER, headers); /* custom Host: */ 85 if(res) 86 goto init_failed; 87 88 res_multi_add_handle(cm, eh[num]); 89 if(res) 90 goto init_failed; 91 92 return 0; /* success */ 93 94init_failed: 95 96 curl_easy_cleanup(eh[num]); 97 eh[num] = NULL; 98 99 return res; /* failure */ 100} 101 102static int loop(int num, CURLM *cm, const char *url, const char *userpwd, 103 struct curl_slist *headers) 104{ 105 CURLMsg *msg; 106 long L; 107 int Q, U = -1; 108 fd_set R, W, E; 109 struct timeval T; 110 int res = 0; 111 112 res = init(num, cm, url, userpwd, headers); 113 if(res) 114 return res; 115 116 while(U) { 117 118 int M = -99; 119 120 res_multi_perform(cm, &U); 121 if(res) 122 return res; 123 124 res_test_timedout(); 125 if(res) 126 return res; 127 128 if(U) { 129 FD_ZERO(&R); 130 FD_ZERO(&W); 131 FD_ZERO(&E); 132 133 res_multi_fdset(cm, &R, &W, &E, &M); 134 if(res) 135 return res; 136 137 /* At this point, M is guaranteed to be greater or equal than -1. */ 138 139 res_multi_timeout(cm, &L); 140 if(res) 141 return res; 142 143 /* At this point, L is guaranteed to be greater or equal than -1. */ 144 145 if(L != -1) { 146 int itimeout; 147#if LONG_MAX > INT_MAX 148 itimeout = (L > INT_MAX) ? INT_MAX : (int)L; 149#else 150 itimeout = (int)L; 151#endif 152 T.tv_sec = itimeout/1000; 153 T.tv_usec = (itimeout%1000)*1000; 154 } 155 else { 156 T.tv_sec = 5; 157 T.tv_usec = 0; 158 } 159 160 res_select_test(M + 1, &R, &W, &E, &T); 161 if(res) 162 return res; 163 } 164 165 while(1) { 166 msg = curl_multi_info_read(cm, &Q); 167 if(!msg) 168 break; 169 if(msg->msg == CURLMSG_DONE) { 170 int i; 171 CURL *e = msg->easy_handle; 172 fprintf(stderr, "R: %d - %s\n", (int)msg->data.result, 173 curl_easy_strerror(msg->data.result)); 174 curl_multi_remove_handle(cm, e); 175 curl_easy_cleanup(e); 176 for(i = 0; i < NUM_HANDLES; i++) { 177 if(eh[i] == e) { 178 eh[i] = NULL; 179 break; 180 } 181 } 182 } 183 else 184 fprintf(stderr, "E: CURLMsg (%d)\n", (int)msg->msg); 185 } 186 187 res_test_timedout(); 188 if(res) 189 return res; 190 } 191 192 return 0; /* success */ 193} 194 195int test(char *URL) 196{ 197 CURLM *cm = NULL; 198 struct curl_slist *headers = NULL; 199 char buffer[246]; /* naively fixed-size */ 200 int res = 0; 201 int i; 202 203 for(i = 0; i < NUM_HANDLES; i++) 204 eh[i] = NULL; 205 206 start_test_timing(); 207 208 if(test_argc < 4) 209 return 99; 210 211 msnprintf(buffer, sizeof(buffer), "Host: %s", HOST); 212 213 /* now add a custom Host: header */ 214 headers = curl_slist_append(headers, buffer); 215 if(!headers) { 216 fprintf(stderr, "curl_slist_append() failed\n"); 217 return TEST_ERR_MAJOR_BAD; 218 } 219 220 res_global_init(CURL_GLOBAL_ALL); 221 if(res) { 222 curl_slist_free_all(headers); 223 return res; 224 } 225 226 res_multi_init(cm); 227 if(res) { 228 curl_global_cleanup(); 229 curl_slist_free_all(headers); 230 return res; 231 } 232 233 res = loop(0, cm, URL, PROXYUSERPWD, headers); 234 if(res) 235 goto test_cleanup; 236 237 fprintf(stderr, "lib540: now we do the request again\n"); 238 239 res = loop(1, cm, URL, PROXYUSERPWD, headers); 240 241test_cleanup: 242 243 /* proper cleanup sequence - type PB */ 244 245 for(i = 0; i < NUM_HANDLES; i++) { 246 curl_multi_remove_handle(cm, eh[i]); 247 curl_easy_cleanup(eh[i]); 248 } 249 250 curl_multi_cleanup(cm); 251 curl_global_cleanup(); 252 253 curl_slist_free_all(headers); 254 255 return res; 256} 257