tizen 2.3.1 release
[external/curl.git] / lib / netrc.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, 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 http://curl.haxx.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  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #ifdef HAVE_PWD_H
26 #include <pwd.h>
27 #endif
28
29 #include <curl/curl.h>
30 #include "netrc.h"
31
32 #include "strequal.h"
33 #include "strtok.h"
34 #include "curl_memory.h"
35 #include "rawstr.h"
36
37 #define _MPRINTF_REPLACE /* use our functions only */
38 #include <curl/mprintf.h>
39
40 /* The last #include file should be: */
41 #include "memdebug.h"
42
43 /* Get user and password from .netrc when given a machine name */
44
45 enum host_lookup_state {
46   NOTHING,
47   HOSTFOUND,    /* the 'machine' keyword was found */
48   HOSTVALID     /* this is "our" machine! */
49 };
50
51 /*
52  * @unittest: 1304
53  *
54  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
55  * in.
56  */
57 int Curl_parsenetrc(const char *host,
58                     char **loginp,
59                     char **passwordp,
60                     char *netrcfile)
61 {
62   FILE *file;
63   int retcode=1;
64   int specific_login = (*loginp && **loginp != 0);
65   bool netrc_alloc = FALSE;
66   enum host_lookup_state state=NOTHING;
67
68   char state_login=0;      /* Found a login keyword */
69   char state_password=0;   /* Found a password keyword */
70   int state_our_login=FALSE;  /* With specific_login, found *our* login name */
71
72 #define NETRC DOT_CHAR "netrc"
73
74   if(!netrcfile) {
75     bool home_alloc = FALSE;
76     char *home = curl_getenv("HOME"); /* portable environment reader */
77     if(home) {
78       home_alloc = TRUE;
79 #if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
80     }
81     else {
82       struct passwd pw, *pw_res;
83       char pwbuf[1024];
84       if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
85          && pw_res) {
86         home = strdup(pw.pw_dir);
87         if(!home)
88           return CURLE_OUT_OF_MEMORY;
89         home_alloc = TRUE;
90       }
91 #elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
92     }
93     else {
94       struct passwd *pw;
95       pw= getpwuid(geteuid());
96       if(pw) {
97         home = pw->pw_dir;
98       }
99 #endif
100     }
101
102     if(!home)
103       return retcode; /* no home directory found (or possibly out of memory) */
104
105     netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
106     if(home_alloc)
107       Curl_safefree(home);
108     if(!netrcfile) {
109       return -1;
110     }
111     netrc_alloc = TRUE;
112   }
113
114   file = fopen(netrcfile, "r");
115   if(netrc_alloc)
116     Curl_safefree(netrcfile);
117   if(file) {
118     char *tok;
119     char *tok_buf;
120     bool done=FALSE;
121     char netrcbuffer[256];
122     int  netrcbuffsize = (int)sizeof(netrcbuffer);
123
124     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
125       tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
126       while(!done && tok) {
127
128         if((*loginp && **loginp) && (*passwordp && **passwordp)) {
129           done=TRUE;
130           break;
131         }
132
133         switch(state) {
134         case NOTHING:
135           if(Curl_raw_equal("machine", tok)) {
136             /* the next tok is the machine name, this is in itself the
137                delimiter that starts the stuff entered for this machine,
138                after this we need to search for 'login' and
139                'password'. */
140             state=HOSTFOUND;
141           }
142           break;
143         case HOSTFOUND:
144           if(Curl_raw_equal(host, tok)) {
145             /* and yes, this is our host! */
146             state=HOSTVALID;
147             retcode=0; /* we did find our host */
148           }
149           else
150             /* not our host */
151             state=NOTHING;
152           break;
153         case HOSTVALID:
154           /* we are now parsing sub-keywords concerning "our" host */
155           if(state_login) {
156             if(specific_login) {
157               state_our_login = Curl_raw_equal(*loginp, tok);
158             }
159             else {
160               free(*loginp);
161               *loginp = strdup(tok);
162               if(!*loginp) {
163                 retcode = -1; /* allocation failed */
164                 goto out;
165               }
166             }
167             state_login=0;
168           }
169           else if(state_password) {
170             if(state_our_login || !specific_login) {
171               free(*passwordp);
172               *passwordp = strdup(tok);
173               if(!*passwordp) {
174                 retcode = -1; /* allocation failed */
175                 goto out;
176               }
177             }
178             state_password=0;
179           }
180           else if(Curl_raw_equal("login", tok))
181             state_login=1;
182           else if(Curl_raw_equal("password", tok))
183             state_password=1;
184           else if(Curl_raw_equal("machine", tok)) {
185             /* ok, there's machine here go => */
186             state = HOSTFOUND;
187             state_our_login = FALSE;
188           }
189           break;
190         } /* switch (state) */
191
192         tok = strtok_r(NULL, " \t\n", &tok_buf);
193       } /* while(tok) */
194     } /* while fgets() */
195
196     out:
197     fclose(file);
198   }
199
200   return retcode;
201 }