xref: /aosp_15_r20/external/curl/lib/netrc.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  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_NETRC
27*6236dae4SAndroid Build Coastguard Worker 
28*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_PWD_H
29*6236dae4SAndroid Build Coastguard Worker #include <pwd.h>
30*6236dae4SAndroid Build Coastguard Worker #endif
31*6236dae4SAndroid Build Coastguard Worker 
32*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
33*6236dae4SAndroid Build Coastguard Worker #include "netrc.h"
34*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
35*6236dae4SAndroid Build Coastguard Worker #include "curl_get_line.h"
36*6236dae4SAndroid Build Coastguard Worker 
37*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
38*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
39*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
40*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
41*6236dae4SAndroid Build Coastguard Worker 
42*6236dae4SAndroid Build Coastguard Worker /* Get user and password from .netrc when given a machine name */
43*6236dae4SAndroid Build Coastguard Worker 
44*6236dae4SAndroid Build Coastguard Worker enum host_lookup_state {
45*6236dae4SAndroid Build Coastguard Worker   NOTHING,
46*6236dae4SAndroid Build Coastguard Worker   HOSTFOUND,    /* the 'machine' keyword was found */
47*6236dae4SAndroid Build Coastguard Worker   HOSTVALID,    /* this is "our" machine! */
48*6236dae4SAndroid Build Coastguard Worker   MACDEF
49*6236dae4SAndroid Build Coastguard Worker };
50*6236dae4SAndroid Build Coastguard Worker 
51*6236dae4SAndroid Build Coastguard Worker enum found_state {
52*6236dae4SAndroid Build Coastguard Worker   NONE,
53*6236dae4SAndroid Build Coastguard Worker   LOGIN,
54*6236dae4SAndroid Build Coastguard Worker   PASSWORD
55*6236dae4SAndroid Build Coastguard Worker };
56*6236dae4SAndroid Build Coastguard Worker 
57*6236dae4SAndroid Build Coastguard Worker #define NETRC_FILE_MISSING 1
58*6236dae4SAndroid Build Coastguard Worker #define NETRC_FAILED -1
59*6236dae4SAndroid Build Coastguard Worker #define NETRC_SUCCESS 0
60*6236dae4SAndroid Build Coastguard Worker 
61*6236dae4SAndroid Build Coastguard Worker #define MAX_NETRC_LINE 4096
62*6236dae4SAndroid Build Coastguard Worker #define MAX_NETRC_FILE (64*1024)
63*6236dae4SAndroid Build Coastguard Worker #define MAX_NETRC_TOKEN 128
64*6236dae4SAndroid Build Coastguard Worker 
file2memory(const char * filename,struct dynbuf * filebuf)65*6236dae4SAndroid Build Coastguard Worker static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
66*6236dae4SAndroid Build Coastguard Worker {
67*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
68*6236dae4SAndroid Build Coastguard Worker   FILE *file = fopen(filename, FOPEN_READTEXT);
69*6236dae4SAndroid Build Coastguard Worker   struct dynbuf linebuf;
70*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
71*6236dae4SAndroid Build Coastguard Worker 
72*6236dae4SAndroid Build Coastguard Worker   if(file) {
73*6236dae4SAndroid Build Coastguard Worker     while(Curl_get_line(&linebuf, file)) {
74*6236dae4SAndroid Build Coastguard Worker       const char *line = Curl_dyn_ptr(&linebuf);
75*6236dae4SAndroid Build Coastguard Worker       /* skip comments on load */
76*6236dae4SAndroid Build Coastguard Worker       while(ISBLANK(*line))
77*6236dae4SAndroid Build Coastguard Worker         line++;
78*6236dae4SAndroid Build Coastguard Worker       if(*line == '#')
79*6236dae4SAndroid Build Coastguard Worker         continue;
80*6236dae4SAndroid Build Coastguard Worker       result = Curl_dyn_add(filebuf, line);
81*6236dae4SAndroid Build Coastguard Worker       if(result)
82*6236dae4SAndroid Build Coastguard Worker         goto done;
83*6236dae4SAndroid Build Coastguard Worker     }
84*6236dae4SAndroid Build Coastguard Worker   }
85*6236dae4SAndroid Build Coastguard Worker done:
86*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&linebuf);
87*6236dae4SAndroid Build Coastguard Worker   if(file)
88*6236dae4SAndroid Build Coastguard Worker     fclose(file);
89*6236dae4SAndroid Build Coastguard Worker   return result;
90*6236dae4SAndroid Build Coastguard Worker }
91*6236dae4SAndroid Build Coastguard Worker 
92*6236dae4SAndroid Build Coastguard Worker /*
93*6236dae4SAndroid Build Coastguard Worker  * Returns zero on success.
94*6236dae4SAndroid Build Coastguard Worker  */
parsenetrc(struct store_netrc * store,const char * host,char ** loginp,char ** passwordp,const char * netrcfile)95*6236dae4SAndroid Build Coastguard Worker static int parsenetrc(struct store_netrc *store,
96*6236dae4SAndroid Build Coastguard Worker                       const char *host,
97*6236dae4SAndroid Build Coastguard Worker                       char **loginp,
98*6236dae4SAndroid Build Coastguard Worker                       char **passwordp,
99*6236dae4SAndroid Build Coastguard Worker                       const char *netrcfile)
100*6236dae4SAndroid Build Coastguard Worker {
101*6236dae4SAndroid Build Coastguard Worker   int retcode = NETRC_FILE_MISSING;
102*6236dae4SAndroid Build Coastguard Worker   char *login = *loginp;
103*6236dae4SAndroid Build Coastguard Worker   char *password = *passwordp;
104*6236dae4SAndroid Build Coastguard Worker   bool specific_login = (login && *login != 0);
105*6236dae4SAndroid Build Coastguard Worker   bool login_alloc = FALSE;
106*6236dae4SAndroid Build Coastguard Worker   bool password_alloc = FALSE;
107*6236dae4SAndroid Build Coastguard Worker   enum host_lookup_state state = NOTHING;
108*6236dae4SAndroid Build Coastguard Worker   enum found_state found = NONE;
109*6236dae4SAndroid Build Coastguard Worker   bool our_login = TRUE;  /* With specific_login, found *our* login name (or
110*6236dae4SAndroid Build Coastguard Worker                              login-less line) */
111*6236dae4SAndroid Build Coastguard Worker   bool done = FALSE;
112*6236dae4SAndroid Build Coastguard Worker   char *netrcbuffer;
113*6236dae4SAndroid Build Coastguard Worker   struct dynbuf token;
114*6236dae4SAndroid Build Coastguard Worker   struct dynbuf *filebuf = &store->filebuf;
115*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&token, MAX_NETRC_TOKEN);
116*6236dae4SAndroid Build Coastguard Worker 
117*6236dae4SAndroid Build Coastguard Worker   if(!store->loaded) {
118*6236dae4SAndroid Build Coastguard Worker     if(file2memory(netrcfile, filebuf))
119*6236dae4SAndroid Build Coastguard Worker       return NETRC_FAILED;
120*6236dae4SAndroid Build Coastguard Worker     store->loaded = TRUE;
121*6236dae4SAndroid Build Coastguard Worker   }
122*6236dae4SAndroid Build Coastguard Worker 
123*6236dae4SAndroid Build Coastguard Worker   netrcbuffer = Curl_dyn_ptr(filebuf);
124*6236dae4SAndroid Build Coastguard Worker 
125*6236dae4SAndroid Build Coastguard Worker   while(!done) {
126*6236dae4SAndroid Build Coastguard Worker     char *tok = netrcbuffer;
127*6236dae4SAndroid Build Coastguard Worker     while(tok) {
128*6236dae4SAndroid Build Coastguard Worker       char *tok_end;
129*6236dae4SAndroid Build Coastguard Worker       bool quoted;
130*6236dae4SAndroid Build Coastguard Worker       Curl_dyn_reset(&token);
131*6236dae4SAndroid Build Coastguard Worker       while(ISBLANK(*tok))
132*6236dae4SAndroid Build Coastguard Worker         tok++;
133*6236dae4SAndroid Build Coastguard Worker       /* tok is first non-space letter */
134*6236dae4SAndroid Build Coastguard Worker       if(state == MACDEF) {
135*6236dae4SAndroid Build Coastguard Worker         if((*tok == '\n') || (*tok == '\r'))
136*6236dae4SAndroid Build Coastguard Worker           state = NOTHING; /* end of macro definition */
137*6236dae4SAndroid Build Coastguard Worker       }
138*6236dae4SAndroid Build Coastguard Worker 
139*6236dae4SAndroid Build Coastguard Worker       if(!*tok || (*tok == '\n'))
140*6236dae4SAndroid Build Coastguard Worker         /* end of line  */
141*6236dae4SAndroid Build Coastguard Worker         break;
142*6236dae4SAndroid Build Coastguard Worker 
143*6236dae4SAndroid Build Coastguard Worker       /* leading double-quote means quoted string */
144*6236dae4SAndroid Build Coastguard Worker       quoted = (*tok == '\"');
145*6236dae4SAndroid Build Coastguard Worker 
146*6236dae4SAndroid Build Coastguard Worker       tok_end = tok;
147*6236dae4SAndroid Build Coastguard Worker       if(!quoted) {
148*6236dae4SAndroid Build Coastguard Worker         size_t len = 0;
149*6236dae4SAndroid Build Coastguard Worker         while(!ISSPACE(*tok_end)) {
150*6236dae4SAndroid Build Coastguard Worker           tok_end++;
151*6236dae4SAndroid Build Coastguard Worker           len++;
152*6236dae4SAndroid Build Coastguard Worker         }
153*6236dae4SAndroid Build Coastguard Worker         if(!len || Curl_dyn_addn(&token, tok, len)) {
154*6236dae4SAndroid Build Coastguard Worker           retcode = NETRC_FAILED;
155*6236dae4SAndroid Build Coastguard Worker           goto out;
156*6236dae4SAndroid Build Coastguard Worker         }
157*6236dae4SAndroid Build Coastguard Worker       }
158*6236dae4SAndroid Build Coastguard Worker       else {
159*6236dae4SAndroid Build Coastguard Worker         bool escape = FALSE;
160*6236dae4SAndroid Build Coastguard Worker         bool endquote = FALSE;
161*6236dae4SAndroid Build Coastguard Worker         tok_end++; /* pass the leading quote */
162*6236dae4SAndroid Build Coastguard Worker         while(*tok_end) {
163*6236dae4SAndroid Build Coastguard Worker           char s = *tok_end;
164*6236dae4SAndroid Build Coastguard Worker           if(escape) {
165*6236dae4SAndroid Build Coastguard Worker             escape = FALSE;
166*6236dae4SAndroid Build Coastguard Worker             switch(s) {
167*6236dae4SAndroid Build Coastguard Worker             case 'n':
168*6236dae4SAndroid Build Coastguard Worker               s = '\n';
169*6236dae4SAndroid Build Coastguard Worker               break;
170*6236dae4SAndroid Build Coastguard Worker             case 'r':
171*6236dae4SAndroid Build Coastguard Worker               s = '\r';
172*6236dae4SAndroid Build Coastguard Worker               break;
173*6236dae4SAndroid Build Coastguard Worker             case 't':
174*6236dae4SAndroid Build Coastguard Worker               s = '\t';
175*6236dae4SAndroid Build Coastguard Worker               break;
176*6236dae4SAndroid Build Coastguard Worker             }
177*6236dae4SAndroid Build Coastguard Worker           }
178*6236dae4SAndroid Build Coastguard Worker           else if(s == '\\') {
179*6236dae4SAndroid Build Coastguard Worker             escape = TRUE;
180*6236dae4SAndroid Build Coastguard Worker             tok_end++;
181*6236dae4SAndroid Build Coastguard Worker             continue;
182*6236dae4SAndroid Build Coastguard Worker           }
183*6236dae4SAndroid Build Coastguard Worker           else if(s == '\"') {
184*6236dae4SAndroid Build Coastguard Worker             tok_end++; /* pass the ending quote */
185*6236dae4SAndroid Build Coastguard Worker             endquote = TRUE;
186*6236dae4SAndroid Build Coastguard Worker             break;
187*6236dae4SAndroid Build Coastguard Worker           }
188*6236dae4SAndroid Build Coastguard Worker           if(Curl_dyn_addn(&token, &s, 1)) {
189*6236dae4SAndroid Build Coastguard Worker             retcode = NETRC_FAILED;
190*6236dae4SAndroid Build Coastguard Worker             goto out;
191*6236dae4SAndroid Build Coastguard Worker           }
192*6236dae4SAndroid Build Coastguard Worker           tok_end++;
193*6236dae4SAndroid Build Coastguard Worker         }
194*6236dae4SAndroid Build Coastguard Worker         if(escape || !endquote) {
195*6236dae4SAndroid Build Coastguard Worker           /* bad syntax, get out */
196*6236dae4SAndroid Build Coastguard Worker           retcode = NETRC_FAILED;
197*6236dae4SAndroid Build Coastguard Worker           goto out;
198*6236dae4SAndroid Build Coastguard Worker         }
199*6236dae4SAndroid Build Coastguard Worker       }
200*6236dae4SAndroid Build Coastguard Worker 
201*6236dae4SAndroid Build Coastguard Worker       if((login && *login) && (password && *password)) {
202*6236dae4SAndroid Build Coastguard Worker         done = TRUE;
203*6236dae4SAndroid Build Coastguard Worker         break;
204*6236dae4SAndroid Build Coastguard Worker       }
205*6236dae4SAndroid Build Coastguard Worker 
206*6236dae4SAndroid Build Coastguard Worker       tok = Curl_dyn_ptr(&token);
207*6236dae4SAndroid Build Coastguard Worker 
208*6236dae4SAndroid Build Coastguard Worker       switch(state) {
209*6236dae4SAndroid Build Coastguard Worker       case NOTHING:
210*6236dae4SAndroid Build Coastguard Worker         if(strcasecompare("macdef", tok))
211*6236dae4SAndroid Build Coastguard Worker           /* Define a macro. A macro is defined with the specified name; its
212*6236dae4SAndroid Build Coastguard Worker              contents begin with the next .netrc line and continue until a
213*6236dae4SAndroid Build Coastguard Worker              null line (consecutive new-line characters) is encountered. */
214*6236dae4SAndroid Build Coastguard Worker           state = MACDEF;
215*6236dae4SAndroid Build Coastguard Worker         else if(strcasecompare("machine", tok))
216*6236dae4SAndroid Build Coastguard Worker           /* the next tok is the machine name, this is in itself the delimiter
217*6236dae4SAndroid Build Coastguard Worker              that starts the stuff entered for this machine, after this we
218*6236dae4SAndroid Build Coastguard Worker              need to search for 'login' and 'password'. */
219*6236dae4SAndroid Build Coastguard Worker           state = HOSTFOUND;
220*6236dae4SAndroid Build Coastguard Worker         else if(strcasecompare("default", tok)) {
221*6236dae4SAndroid Build Coastguard Worker           state = HOSTVALID;
222*6236dae4SAndroid Build Coastguard Worker           retcode = NETRC_SUCCESS; /* we did find our host */
223*6236dae4SAndroid Build Coastguard Worker         }
224*6236dae4SAndroid Build Coastguard Worker         break;
225*6236dae4SAndroid Build Coastguard Worker       case MACDEF:
226*6236dae4SAndroid Build Coastguard Worker         if(!*tok)
227*6236dae4SAndroid Build Coastguard Worker           state = NOTHING;
228*6236dae4SAndroid Build Coastguard Worker         break;
229*6236dae4SAndroid Build Coastguard Worker       case HOSTFOUND:
230*6236dae4SAndroid Build Coastguard Worker         if(strcasecompare(host, tok)) {
231*6236dae4SAndroid Build Coastguard Worker           /* and yes, this is our host! */
232*6236dae4SAndroid Build Coastguard Worker           state = HOSTVALID;
233*6236dae4SAndroid Build Coastguard Worker           retcode = NETRC_SUCCESS; /* we did find our host */
234*6236dae4SAndroid Build Coastguard Worker         }
235*6236dae4SAndroid Build Coastguard Worker         else
236*6236dae4SAndroid Build Coastguard Worker           /* not our host */
237*6236dae4SAndroid Build Coastguard Worker           state = NOTHING;
238*6236dae4SAndroid Build Coastguard Worker         break;
239*6236dae4SAndroid Build Coastguard Worker       case HOSTVALID:
240*6236dae4SAndroid Build Coastguard Worker         /* we are now parsing sub-keywords concerning "our" host */
241*6236dae4SAndroid Build Coastguard Worker         if(found == LOGIN) {
242*6236dae4SAndroid Build Coastguard Worker           if(specific_login) {
243*6236dae4SAndroid Build Coastguard Worker             our_login = !Curl_timestrcmp(login, tok);
244*6236dae4SAndroid Build Coastguard Worker           }
245*6236dae4SAndroid Build Coastguard Worker           else if(!login || Curl_timestrcmp(login, tok)) {
246*6236dae4SAndroid Build Coastguard Worker             if(login_alloc)
247*6236dae4SAndroid Build Coastguard Worker               free(login);
248*6236dae4SAndroid Build Coastguard Worker             login = strdup(tok);
249*6236dae4SAndroid Build Coastguard Worker             if(!login) {
250*6236dae4SAndroid Build Coastguard Worker               retcode = NETRC_FAILED; /* allocation failed */
251*6236dae4SAndroid Build Coastguard Worker               goto out;
252*6236dae4SAndroid Build Coastguard Worker             }
253*6236dae4SAndroid Build Coastguard Worker             login_alloc = TRUE;
254*6236dae4SAndroid Build Coastguard Worker           }
255*6236dae4SAndroid Build Coastguard Worker           found = NONE;
256*6236dae4SAndroid Build Coastguard Worker         }
257*6236dae4SAndroid Build Coastguard Worker         else if(found == PASSWORD) {
258*6236dae4SAndroid Build Coastguard Worker           if((our_login || !specific_login) &&
259*6236dae4SAndroid Build Coastguard Worker              (!password || Curl_timestrcmp(password, tok))) {
260*6236dae4SAndroid Build Coastguard Worker             if(password_alloc)
261*6236dae4SAndroid Build Coastguard Worker               free(password);
262*6236dae4SAndroid Build Coastguard Worker             password = strdup(tok);
263*6236dae4SAndroid Build Coastguard Worker             if(!password) {
264*6236dae4SAndroid Build Coastguard Worker               retcode = NETRC_FAILED; /* allocation failed */
265*6236dae4SAndroid Build Coastguard Worker               goto out;
266*6236dae4SAndroid Build Coastguard Worker             }
267*6236dae4SAndroid Build Coastguard Worker             password_alloc = TRUE;
268*6236dae4SAndroid Build Coastguard Worker           }
269*6236dae4SAndroid Build Coastguard Worker           found = NONE;
270*6236dae4SAndroid Build Coastguard Worker         }
271*6236dae4SAndroid Build Coastguard Worker         else if(strcasecompare("login", tok))
272*6236dae4SAndroid Build Coastguard Worker           found = LOGIN;
273*6236dae4SAndroid Build Coastguard Worker         else if(strcasecompare("password", tok))
274*6236dae4SAndroid Build Coastguard Worker           found = PASSWORD;
275*6236dae4SAndroid Build Coastguard Worker         else if(strcasecompare("machine", tok)) {
276*6236dae4SAndroid Build Coastguard Worker           /* ok, there is machine here go => */
277*6236dae4SAndroid Build Coastguard Worker           state = HOSTFOUND;
278*6236dae4SAndroid Build Coastguard Worker           found = NONE;
279*6236dae4SAndroid Build Coastguard Worker         }
280*6236dae4SAndroid Build Coastguard Worker         break;
281*6236dae4SAndroid Build Coastguard Worker       } /* switch (state) */
282*6236dae4SAndroid Build Coastguard Worker       tok = ++tok_end;
283*6236dae4SAndroid Build Coastguard Worker     }
284*6236dae4SAndroid Build Coastguard Worker     if(!done) {
285*6236dae4SAndroid Build Coastguard Worker       char *nl = NULL;
286*6236dae4SAndroid Build Coastguard Worker       if(tok)
287*6236dae4SAndroid Build Coastguard Worker         nl = strchr(tok, '\n');
288*6236dae4SAndroid Build Coastguard Worker       if(!nl)
289*6236dae4SAndroid Build Coastguard Worker         break;
290*6236dae4SAndroid Build Coastguard Worker       /* point to next line */
291*6236dae4SAndroid Build Coastguard Worker       netrcbuffer = &nl[1];
292*6236dae4SAndroid Build Coastguard Worker     }
293*6236dae4SAndroid Build Coastguard Worker   } /* while !done */
294*6236dae4SAndroid Build Coastguard Worker 
295*6236dae4SAndroid Build Coastguard Worker out:
296*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&token);
297*6236dae4SAndroid Build Coastguard Worker   if(!retcode) {
298*6236dae4SAndroid Build Coastguard Worker     /* success */
299*6236dae4SAndroid Build Coastguard Worker     if(login_alloc) {
300*6236dae4SAndroid Build Coastguard Worker       free(*loginp);
301*6236dae4SAndroid Build Coastguard Worker       *loginp = login;
302*6236dae4SAndroid Build Coastguard Worker     }
303*6236dae4SAndroid Build Coastguard Worker     if(password_alloc) {
304*6236dae4SAndroid Build Coastguard Worker       free(*passwordp);
305*6236dae4SAndroid Build Coastguard Worker       *passwordp = password;
306*6236dae4SAndroid Build Coastguard Worker     }
307*6236dae4SAndroid Build Coastguard Worker   }
308*6236dae4SAndroid Build Coastguard Worker   else {
309*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(filebuf);
310*6236dae4SAndroid Build Coastguard Worker     if(login_alloc)
311*6236dae4SAndroid Build Coastguard Worker       free(login);
312*6236dae4SAndroid Build Coastguard Worker     if(password_alloc)
313*6236dae4SAndroid Build Coastguard Worker       free(password);
314*6236dae4SAndroid Build Coastguard Worker   }
315*6236dae4SAndroid Build Coastguard Worker 
316*6236dae4SAndroid Build Coastguard Worker   return retcode;
317*6236dae4SAndroid Build Coastguard Worker }
318*6236dae4SAndroid Build Coastguard Worker 
319*6236dae4SAndroid Build Coastguard Worker /*
320*6236dae4SAndroid Build Coastguard Worker  * @unittest: 1304
321*6236dae4SAndroid Build Coastguard Worker  *
322*6236dae4SAndroid Build Coastguard Worker  * *loginp and *passwordp MUST be allocated if they are not NULL when passed
323*6236dae4SAndroid Build Coastguard Worker  * in.
324*6236dae4SAndroid Build Coastguard Worker  */
Curl_parsenetrc(struct store_netrc * store,const char * host,char ** loginp,char ** passwordp,char * netrcfile)325*6236dae4SAndroid Build Coastguard Worker int Curl_parsenetrc(struct store_netrc *store, const char *host,
326*6236dae4SAndroid Build Coastguard Worker                     char **loginp, char **passwordp,
327*6236dae4SAndroid Build Coastguard Worker                     char *netrcfile)
328*6236dae4SAndroid Build Coastguard Worker {
329*6236dae4SAndroid Build Coastguard Worker   int retcode = 1;
330*6236dae4SAndroid Build Coastguard Worker   char *filealloc = NULL;
331*6236dae4SAndroid Build Coastguard Worker 
332*6236dae4SAndroid Build Coastguard Worker   if(!netrcfile) {
333*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
334*6236dae4SAndroid Build Coastguard Worker     char pwbuf[1024];
335*6236dae4SAndroid Build Coastguard Worker #endif
336*6236dae4SAndroid Build Coastguard Worker     char *home = NULL;
337*6236dae4SAndroid Build Coastguard Worker     char *homea = curl_getenv("HOME"); /* portable environment reader */
338*6236dae4SAndroid Build Coastguard Worker     if(homea) {
339*6236dae4SAndroid Build Coastguard Worker       home = homea;
340*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
341*6236dae4SAndroid Build Coastguard Worker     }
342*6236dae4SAndroid Build Coastguard Worker     else {
343*6236dae4SAndroid Build Coastguard Worker       struct passwd pw, *pw_res;
344*6236dae4SAndroid Build Coastguard Worker       if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
345*6236dae4SAndroid Build Coastguard Worker          && pw_res) {
346*6236dae4SAndroid Build Coastguard Worker         home = pw.pw_dir;
347*6236dae4SAndroid Build Coastguard Worker       }
348*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
349*6236dae4SAndroid Build Coastguard Worker     }
350*6236dae4SAndroid Build Coastguard Worker     else {
351*6236dae4SAndroid Build Coastguard Worker       struct passwd *pw;
352*6236dae4SAndroid Build Coastguard Worker       pw = getpwuid(geteuid());
353*6236dae4SAndroid Build Coastguard Worker       if(pw) {
354*6236dae4SAndroid Build Coastguard Worker         home = pw->pw_dir;
355*6236dae4SAndroid Build Coastguard Worker       }
356*6236dae4SAndroid Build Coastguard Worker #elif defined(_WIN32)
357*6236dae4SAndroid Build Coastguard Worker     }
358*6236dae4SAndroid Build Coastguard Worker     else {
359*6236dae4SAndroid Build Coastguard Worker       homea = curl_getenv("USERPROFILE");
360*6236dae4SAndroid Build Coastguard Worker       if(homea) {
361*6236dae4SAndroid Build Coastguard Worker         home = homea;
362*6236dae4SAndroid Build Coastguard Worker       }
363*6236dae4SAndroid Build Coastguard Worker #endif
364*6236dae4SAndroid Build Coastguard Worker     }
365*6236dae4SAndroid Build Coastguard Worker 
366*6236dae4SAndroid Build Coastguard Worker     if(!home)
367*6236dae4SAndroid Build Coastguard Worker       return retcode; /* no home directory found (or possibly out of
368*6236dae4SAndroid Build Coastguard Worker                          memory) */
369*6236dae4SAndroid Build Coastguard Worker 
370*6236dae4SAndroid Build Coastguard Worker     filealloc = aprintf("%s%s.netrc", home, DIR_CHAR);
371*6236dae4SAndroid Build Coastguard Worker     if(!filealloc) {
372*6236dae4SAndroid Build Coastguard Worker       free(homea);
373*6236dae4SAndroid Build Coastguard Worker       return -1;
374*6236dae4SAndroid Build Coastguard Worker     }
375*6236dae4SAndroid Build Coastguard Worker     retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
376*6236dae4SAndroid Build Coastguard Worker     free(filealloc);
377*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
378*6236dae4SAndroid Build Coastguard Worker     if(retcode == NETRC_FILE_MISSING) {
379*6236dae4SAndroid Build Coastguard Worker       /* fallback to the old-style "_netrc" file */
380*6236dae4SAndroid Build Coastguard Worker       filealloc = aprintf("%s%s_netrc", home, DIR_CHAR);
381*6236dae4SAndroid Build Coastguard Worker       if(!filealloc) {
382*6236dae4SAndroid Build Coastguard Worker         free(homea);
383*6236dae4SAndroid Build Coastguard Worker         return -1;
384*6236dae4SAndroid Build Coastguard Worker       }
385*6236dae4SAndroid Build Coastguard Worker       retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
386*6236dae4SAndroid Build Coastguard Worker       free(filealloc);
387*6236dae4SAndroid Build Coastguard Worker     }
388*6236dae4SAndroid Build Coastguard Worker #endif
389*6236dae4SAndroid Build Coastguard Worker     free(homea);
390*6236dae4SAndroid Build Coastguard Worker   }
391*6236dae4SAndroid Build Coastguard Worker   else
392*6236dae4SAndroid Build Coastguard Worker     retcode = parsenetrc(store, host, loginp, passwordp, netrcfile);
393*6236dae4SAndroid Build Coastguard Worker   return retcode;
394*6236dae4SAndroid Build Coastguard Worker }
395*6236dae4SAndroid Build Coastguard Worker 
Curl_netrc_init(struct store_netrc * s)396*6236dae4SAndroid Build Coastguard Worker void Curl_netrc_init(struct store_netrc *s)
397*6236dae4SAndroid Build Coastguard Worker {
398*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
399*6236dae4SAndroid Build Coastguard Worker   s->loaded = FALSE;
400*6236dae4SAndroid Build Coastguard Worker }
Curl_netrc_cleanup(struct store_netrc * s)401*6236dae4SAndroid Build Coastguard Worker void Curl_netrc_cleanup(struct store_netrc *s)
402*6236dae4SAndroid Build Coastguard Worker {
403*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&s->filebuf);
404*6236dae4SAndroid Build Coastguard Worker   s->loaded = FALSE;
405*6236dae4SAndroid Build Coastguard Worker }
406*6236dae4SAndroid Build Coastguard Worker #endif
407