VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/netrc.c@ 105284

Last change on this file since 105284 was 104083, checked in by vboxsync, 11 months ago

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <[email protected]>, 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
25#include "curl_setup.h"
26#ifndef CURL_DISABLE_NETRC
27
28#ifdef HAVE_PWD_H
29#include <pwd.h>
30#endif
31
32#include <curl/curl.h>
33#include "netrc.h"
34#include "strtok.h"
35#include "strcase.h"
36#include "curl_get_line.h"
37
38/* The last 3 #include files should be in this order */
39#include "curl_printf.h"
40#include "curl_memory.h"
41#include "memdebug.h"
42
43/* Get user and password from .netrc when given a machine name */
44
45enum host_lookup_state {
46 NOTHING,
47 HOSTFOUND, /* the 'machine' keyword was found */
48 HOSTVALID, /* this is "our" machine! */
49 MACDEF
50};
51
52#define NETRC_FILE_MISSING 1
53#define NETRC_FAILED -1
54#define NETRC_SUCCESS 0
55
56#define MAX_NETRC_LINE 4096
57
58/*
59 * Returns zero on success.
60 */
61static int parsenetrc(const char *host,
62 char **loginp,
63 char **passwordp,
64 char *netrcfile)
65{
66 FILE *file;
67 int retcode = NETRC_FILE_MISSING;
68 char *login = *loginp;
69 char *password = *passwordp;
70 bool specific_login = (login && *login != 0);
71 bool login_alloc = FALSE;
72 bool password_alloc = FALSE;
73 enum host_lookup_state state = NOTHING;
74
75 char state_login = 0; /* Found a login keyword */
76 char state_password = 0; /* Found a password keyword */
77 int state_our_login = TRUE; /* With specific_login, found *our* login
78 name (or login-less line) */
79
80 DEBUGASSERT(netrcfile);
81
82 file = fopen(netrcfile, FOPEN_READTEXT);
83 if(file) {
84 bool done = FALSE;
85 struct dynbuf buf;
86 Curl_dyn_init(&buf, MAX_NETRC_LINE);
87
88 while(!done && Curl_get_line(&buf, file)) {
89 char *tok;
90 char *tok_end;
91 bool quoted;
92 char *netrcbuffer = Curl_dyn_ptr(&buf);
93 if(state == MACDEF) {
94 if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
95 state = NOTHING;
96 else
97 continue;
98 }
99 tok = netrcbuffer;
100 while(tok) {
101 while(ISBLANK(*tok))
102 tok++;
103 /* tok is first non-space letter */
104 if(!*tok || (*tok == '#'))
105 /* end of line or the rest is a comment */
106 break;
107
108 /* leading double-quote means quoted string */
109 quoted = (*tok == '\"');
110
111 tok_end = tok;
112 if(!quoted) {
113 while(!ISSPACE(*tok_end))
114 tok_end++;
115 *tok_end = 0;
116 }
117 else {
118 bool escape = FALSE;
119 bool endquote = FALSE;
120 char *store = tok;
121 tok_end++; /* pass the leading quote */
122 while(*tok_end) {
123 char s = *tok_end;
124 if(escape) {
125 escape = FALSE;
126 switch(s) {
127 case 'n':
128 s = '\n';
129 break;
130 case 'r':
131 s = '\r';
132 break;
133 case 't':
134 s = '\t';
135 break;
136 }
137 }
138 else if(s == '\\') {
139 escape = TRUE;
140 tok_end++;
141 continue;
142 }
143 else if(s == '\"') {
144 tok_end++; /* pass the ending quote */
145 endquote = TRUE;
146 break;
147 }
148 *store++ = s;
149 tok_end++;
150 }
151 *store = 0;
152 if(escape || !endquote) {
153 /* bad syntax, get out */
154 retcode = NETRC_FAILED;
155 goto out;
156 }
157 }
158
159 if((login && *login) && (password && *password)) {
160 done = TRUE;
161 break;
162 }
163
164 switch(state) {
165 case NOTHING:
166 if(strcasecompare("macdef", tok)) {
167 /* Define a macro. A macro is defined with the specified name; its
168 contents begin with the next .netrc line and continue until a
169 null line (consecutive new-line characters) is encountered. */
170 state = MACDEF;
171 }
172 else if(strcasecompare("machine", tok)) {
173 /* the next tok is the machine name, this is in itself the
174 delimiter that starts the stuff entered for this machine,
175 after this we need to search for 'login' and
176 'password'. */
177 state = HOSTFOUND;
178 }
179 else if(strcasecompare("default", tok)) {
180 state = HOSTVALID;
181 retcode = NETRC_SUCCESS; /* we did find our host */
182 }
183 break;
184 case MACDEF:
185 if(!strlen(tok)) {
186 state = NOTHING;
187 }
188 break;
189 case HOSTFOUND:
190 if(strcasecompare(host, tok)) {
191 /* and yes, this is our host! */
192 state = HOSTVALID;
193 retcode = NETRC_SUCCESS; /* we did find our host */
194 }
195 else
196 /* not our host */
197 state = NOTHING;
198 break;
199 case HOSTVALID:
200 /* we are now parsing sub-keywords concerning "our" host */
201 if(state_login) {
202 if(specific_login) {
203 state_our_login = !Curl_timestrcmp(login, tok);
204 }
205 else if(!login || Curl_timestrcmp(login, tok)) {
206 if(login_alloc) {
207 free(login);
208 login_alloc = FALSE;
209 }
210 login = strdup(tok);
211 if(!login) {
212 retcode = NETRC_FAILED; /* allocation failed */
213 goto out;
214 }
215 login_alloc = TRUE;
216 }
217 state_login = 0;
218 }
219 else if(state_password) {
220 if((state_our_login || !specific_login)
221 && (!password || Curl_timestrcmp(password, tok))) {
222 if(password_alloc) {
223 free(password);
224 password_alloc = FALSE;
225 }
226 password = strdup(tok);
227 if(!password) {
228 retcode = NETRC_FAILED; /* allocation failed */
229 goto out;
230 }
231 password_alloc = TRUE;
232 }
233 state_password = 0;
234 }
235 else if(strcasecompare("login", tok))
236 state_login = 1;
237 else if(strcasecompare("password", tok))
238 state_password = 1;
239 else if(strcasecompare("machine", tok)) {
240 /* ok, there's machine here go => */
241 state = HOSTFOUND;
242 state_our_login = FALSE;
243 }
244 break;
245 } /* switch (state) */
246 tok = ++tok_end;
247 }
248 } /* while Curl_get_line() */
249
250out:
251 Curl_dyn_free(&buf);
252 if(!retcode) {
253 /* success */
254 if(login_alloc) {
255 if(*loginp)
256 free(*loginp);
257 *loginp = login;
258 }
259 if(password_alloc) {
260 if(*passwordp)
261 free(*passwordp);
262 *passwordp = password;
263 }
264 }
265 else {
266 if(login_alloc)
267 free(login);
268 if(password_alloc)
269 free(password);
270 }
271 fclose(file);
272 }
273
274 return retcode;
275}
276
277/*
278 * @unittest: 1304
279 *
280 * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
281 * in.
282 */
283int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
284 char *netrcfile)
285{
286 int retcode = 1;
287 char *filealloc = NULL;
288
289 if(!netrcfile) {
290#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
291 char pwbuf[1024];
292#endif
293 char *home = NULL;
294 char *homea = curl_getenv("HOME"); /* portable environment reader */
295 if(homea) {
296 home = homea;
297#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
298 }
299 else {
300 struct passwd pw, *pw_res;
301 if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
302 && pw_res) {
303 home = pw.pw_dir;
304 }
305#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
306 }
307 else {
308 struct passwd *pw;
309 pw = getpwuid(geteuid());
310 if(pw) {
311 home = pw->pw_dir;
312 }
313#elif defined(_WIN32)
314 }
315 else {
316 homea = curl_getenv("USERPROFILE");
317 if(homea) {
318 home = homea;
319 }
320#endif
321 }
322
323 if(!home)
324 return retcode; /* no home directory found (or possibly out of
325 memory) */
326
327 filealloc = curl_maprintf("%s%s.netrc", home, DIR_CHAR);
328 if(!filealloc) {
329 free(homea);
330 return -1;
331 }
332 retcode = parsenetrc(host, loginp, passwordp, filealloc);
333 free(filealloc);
334#ifdef _WIN32
335 if(retcode == NETRC_FILE_MISSING) {
336 /* fallback to the old-style "_netrc" file */
337 filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
338 if(!filealloc) {
339 free(homea);
340 return -1;
341 }
342 retcode = parsenetrc(host, loginp, passwordp, filealloc);
343 free(filealloc);
344 }
345#endif
346 free(homea);
347 }
348 else
349 retcode = parsenetrc(host, loginp, passwordp, netrcfile);
350 return retcode;
351}
352
353#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette