xref: /third_party/curl/tests/server/fake_ntlm.c (revision 13498266)
1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Mandy Wu, <mandy.wu@intel.com>
9 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10 *
11 * This software is licensed as described in the file COPYING, which
12 * you should have received as part of this distribution. The terms
13 * are also available at https://curl.se/docs/copyright.html.
14 *
15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16 * copies of the Software, and permit persons to whom the Software is
17 * furnished to do so, under the terms of the COPYING file.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 * SPDX-License-Identifier: curl
23 *
24 ***************************************************************************/
25#include "server_setup.h"
26
27/*
28 * This is a fake ntlm_auth, which is used for testing NTLM single-sign-on.
29 * When DEBUGBUILD is defined, libcurl invoke this tool instead of real winbind
30 * daemon helper /usr/bin/ntlm_auth. This tool will accept commands and
31 * responses with a pre-written string saved in test case test2005.
32 */
33
34#define ENABLE_CURLX_PRINTF
35#include "curlx.h" /* from the private lib dir */
36#include "getpart.h"
37#include "util.h"
38
39/* include memdebug.h last */
40#include "memdebug.h"
41
42#define LOGFILE "%s/fake_ntlm%ld.log"
43static const char *logdir = "log";
44
45const char *serverlogfile;
46
47/*
48 * Returns an allocated buffer with printable representation of input
49 * buffer contents or returns NULL on out of memory condition.
50 */
51static char *printable(char *inbuf, size_t inlength)
52{
53  char *outbuf;
54  char *newbuf;
55  size_t newsize;
56  size_t outsize;
57  size_t outincr = 0;
58  size_t i, o = 0;
59
60#define HEX_FMT_STR  "[0x%02X]"
61#define HEX_STR_LEN  6
62#define NOTHING_STR  "[NOTHING]"
63#define NOTHING_LEN  9
64
65  if(!inlength)
66    inlength = strlen(inbuf);
67
68  if(inlength) {
69    outincr = ((inlength/2) < (HEX_STR_LEN + 1)) ?
70      HEX_STR_LEN + 1 : inlength/2;
71    outsize = inlength + outincr;
72  }
73  else
74    outsize = NOTHING_LEN + 1;
75
76  outbuf = malloc(outsize);
77  if(!outbuf)
78    return NULL;
79
80  if(!inlength) {
81    msnprintf(&outbuf[0], outsize, "%s", NOTHING_STR);
82    return outbuf;
83  }
84
85  for(i = 0; i<inlength; i++) {
86
87    if(o > outsize - (HEX_STR_LEN + 1)) {
88      newsize = outsize + outincr;
89      newbuf = realloc(outbuf, newsize);
90      if(!newbuf) {
91        free(outbuf);
92        return NULL;
93      }
94      outbuf = newbuf;
95      outsize = newsize;
96    }
97
98    if((inbuf[i] > 0x20) && (inbuf[i] < 0x7F)) {
99      outbuf[o] = inbuf[i];
100      o++;
101    }
102    else {
103      msnprintf(&outbuf[o], outsize - o, HEX_FMT_STR, inbuf[i]);
104      o += HEX_STR_LEN;
105    }
106
107  }
108  outbuf[o] = '\0';
109
110  return outbuf;
111}
112
113int main(int argc, char *argv[])
114{
115  char buf[1024];
116  char logfilename[256];
117  FILE *stream;
118  int error;
119  char *type1_input = NULL, *type3_input = NULL;
120  char *type1_output = NULL, *type3_output = NULL;
121  size_t size = 0;
122  long testnum;
123  const char *env;
124  int arg = 1;
125  const char *helper_user = "unknown";
126  const char *helper_proto = "unknown";
127  const char *helper_domain = "unknown";
128  bool use_cached_creds = FALSE;
129  char *msgbuf;
130
131  buf[0] = '\0';
132
133  while(argc > arg) {
134    if(!strcmp("--use-cached-creds", argv[arg])) {
135      use_cached_creds = TRUE;
136      arg++;
137    }
138    else if(!strcmp("--helper-protocol", argv[arg])) {
139      arg++;
140      if(argc > arg)
141        helper_proto = argv[arg++];
142    }
143    else if(!strcmp("--username", argv[arg])) {
144      arg++;
145      if(argc > arg)
146        helper_user = argv[arg++];
147    }
148    else if(!strcmp("--domain", argv[arg])) {
149      arg++;
150      if(argc > arg)
151        helper_domain = argv[arg++];
152    }
153    else {
154      puts("Usage: fake_ntlm [option]\n"
155           " --use-cached-creds\n"
156           " --helper-protocol [protocol]\n"
157           " --username [username]\n"
158           " --domain [domain]");
159      exit(1);
160    }
161  }
162
163  env = getenv("CURL_NTLM_LOGDIR");
164  if(env) {
165    logdir = env;
166  }
167
168  env = getenv("CURL_NTLM_AUTH_TESTNUM");
169  if(env) {
170    char *endptr;
171    long lnum = strtol(env, &endptr, 10);
172    if((endptr != env + strlen(env)) || (lnum < 1L)) {
173      fprintf(stderr, "Test number not valid in CURL_NTLM_AUTH_TESTNUM");
174      exit(1);
175    }
176    testnum = lnum;
177  }
178  else {
179    fprintf(stderr, "Test number not specified in CURL_NTLM_AUTH_TESTNUM");
180    exit(1);
181  }
182
183  /* logmsg cannot be used until this file name is set */
184  msnprintf(logfilename, sizeof(logfilename), LOGFILE, logdir, testnum);
185  serverlogfile = logfilename;
186
187  logmsg("fake_ntlm (user: %s) (proto: %s) (domain: %s) (cached creds: %s)",
188         helper_user, helper_proto, helper_domain,
189         (use_cached_creds) ? "yes" : "no");
190
191  env = getenv("CURL_NTLM_AUTH_SRCDIR");
192  if(env) {
193    path = env;
194  }
195
196  stream = test2fopen(testnum, logdir);
197  if(!stream) {
198    error = errno;
199    logmsg("fopen() failed with error: %d %s", error, strerror(error));
200    logmsg("Couldn't open test file %ld", testnum);
201    exit(1);
202  }
203  else {
204    /* get the ntlm_auth input/output */
205    error = getpart(&type1_input, &size, "ntlm_auth_type1", "input", stream);
206    fclose(stream);
207    if(error || size == 0) {
208      logmsg("getpart() type 1 input failed with error: %d", error);
209      exit(1);
210    }
211  }
212
213  stream = test2fopen(testnum, logdir);
214  if(!stream) {
215    error = errno;
216    logmsg("fopen() failed with error: %d %s", error, strerror(error));
217    logmsg("Couldn't open test file %ld", testnum);
218  }
219  else {
220    size = 0;
221    error = getpart(&type3_input, &size, "ntlm_auth_type3", "input", stream);
222    fclose(stream);
223    if(error || size == 0) {
224      logmsg("getpart() type 3 input failed with error: %d", error);
225      exit(1);
226    }
227  }
228
229  while(fgets(buf, sizeof(buf), stdin)) {
230    if(strcmp(buf, type1_input) == 0) {
231      stream = test2fopen(testnum, logdir);
232      if(!stream) {
233        error = errno;
234        logmsg("fopen() failed with error: %d %s", error, strerror(error));
235        logmsg("Couldn't open test file %ld", testnum);
236        exit(1);
237      }
238      else {
239        size = 0;
240        error = getpart(&type1_output, &size, "ntlm_auth_type1", "output",
241                        stream);
242        fclose(stream);
243        if(error || size == 0) {
244          logmsg("getpart() type 1 output failed with error: %d", error);
245          exit(1);
246        }
247      }
248      printf("%s", type1_output);
249      fflush(stdout);
250    }
251    else if(strncmp(buf, type3_input, strlen(type3_input)) == 0) {
252      stream = test2fopen(testnum, logdir);
253      if(!stream) {
254        error = errno;
255        logmsg("fopen() failed with error: %d %s", error, strerror(error));
256        logmsg("Couldn't open test file %ld", testnum);
257        exit(1);
258      }
259      else {
260        size = 0;
261        error = getpart(&type3_output, &size, "ntlm_auth_type3", "output",
262                        stream);
263        fclose(stream);
264        if(error || size == 0) {
265          logmsg("getpart() type 3 output failed with error: %d", error);
266          exit(1);
267        }
268      }
269      printf("%s", type3_output);
270      fflush(stdout);
271    }
272    else {
273      printf("Unknown request\n");
274      msgbuf = printable(buf, 0);
275      if(msgbuf) {
276        logmsg("invalid input: '%s'\n", msgbuf);
277        free(msgbuf);
278      }
279      else
280        logmsg("OOM formatting invalid input: '%s'\n", buf);
281      exit(1);
282    }
283  }
284  logmsg("Exit");
285  return 1;
286}
287