1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2008, 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 * $Id: netrc.c,v 1.43 2008-10-23 11:49:19 bagder Exp $
22 ***************************************************************************/
23
24 #include "setup.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #ifdef HAVE_PWD_H
34 #include <pwd.h>
35 #endif
36 #ifdef VMS
37 #include <unixlib.h>
38 #endif
39
40 #include <curl/curl.h>
41 #include "netrc.h"
42
43 #include "strequal.h"
44 #include "strtok.h"
45 #include "memory.h"
46 #include "rawstr.h"
47
48 #define _MPRINTF_REPLACE /* use our functions only */
49 #include <curl/mprintf.h>
50
51 /* The last #include file should be: */
52 #include "memdebug.h"
53
54 /* Debug this single source file with:
55 'make netrc' then run './netrc'!
56
57 Oh, make sure you have a .netrc file too ;-)
58 */
59
60 /* Get user and password from .netrc when given a machine name */
61
62 enum {
63 NOTHING,
64 HOSTFOUND, /* the 'machine' keyword was found */
65 HOSTCOMPLETE, /* the machine name following the keyword was found too */
66 HOSTVALID, /* this is "our" machine! */
67
68 HOSTEND /* LAST enum */
69 };
70
71 /* make sure we have room for at least this size: */
72 #define LOGINSIZE 64
73 #define PASSWORDSIZE 64
74
75 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
Curl_parsenetrc(const char * host,char * login,char * password,char * netrcfile)76 int Curl_parsenetrc(const char *host,
77 char *login,
78 char *password,
79 char *netrcfile)
80 {
81 FILE *file;
82 int retcode=1;
83 int specific_login = (login[0] != 0);
84 char *home = NULL;
85 bool home_alloc = FALSE;
86 bool netrc_alloc = FALSE;
87 int state=NOTHING;
88
89 char state_login=0; /* Found a login keyword */
90 char state_password=0; /* Found a password keyword */
91 int state_our_login=FALSE; /* With specific_login, found *our* login name */
92
93 #define NETRC DOT_CHAR "netrc"
94
95 #ifdef CURLDEBUG
96 {
97 /* This is a hack to allow testing.
98 * If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
99 * then it's the path to a substitute .netrc for testing purposes *only* */
100
101 char *override = curl_getenv("CURL_DEBUG_NETRC");
102
103 if(override) {
104 fprintf(stderr, "NETRC: overridden " NETRC " file: %s\n", override);
105 netrcfile = override;
106 netrc_alloc = TRUE;
107 }
108 }
109 #endif /* CURLDEBUG */
110 if(!netrcfile) {
111 home = curl_getenv("HOME"); /* portable environment reader */
112 if(home) {
113 home_alloc = TRUE;
114 #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
115 }
116 else {
117 struct passwd *pw;
118 pw= getpwuid(geteuid());
119 if(pw) {
120 #ifdef VMS
121 home = decc_translate_vms(pw->pw_dir);
122 #else
123 home = pw->pw_dir;
124 #endif
125 }
126 #endif
127 }
128
129 if(!home)
130 return -1;
131
132 netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
133 if(!netrcfile) {
134 if(home_alloc)
135 free(home);
136 return -1;
137 }
138 netrc_alloc = TRUE;
139 }
140
141 file = fopen(netrcfile, "r");
142 if(file) {
143 char *tok;
144 char *tok_buf;
145 bool done=FALSE;
146 char netrcbuffer[256];
147
148 while(!done && fgets(netrcbuffer, sizeof(netrcbuffer), file)) {
149 tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
150 while(!done && tok) {
151
152 if(login[0] && password[0]) {
153 done=TRUE;
154 break;
155 }
156
157 switch(state) {
158 case NOTHING:
159 if(Curl_raw_equal("machine", tok)) {
160 /* the next tok is the machine name, this is in itself the
161 delimiter that starts the stuff entered for this machine,
162 after this we need to search for 'login' and
163 'password'. */
164 state=HOSTFOUND;
165 }
166 break;
167 case HOSTFOUND:
168 if(Curl_raw_equal(host, tok)) {
169 /* and yes, this is our host! */
170 state=HOSTVALID;
171 #ifdef _NETRC_DEBUG
172 fprintf(stderr, "HOST: %s\n", tok);
173 #endif
174 retcode=0; /* we did find our host */
175 }
176 else
177 /* not our host */
178 state=NOTHING;
179 break;
180 case HOSTVALID:
181 /* we are now parsing sub-keywords concerning "our" host */
182 if(state_login) {
183 if(specific_login) {
184 state_our_login = Curl_raw_equal(login, tok);
185 }
186 else {
187 strncpy(login, tok, LOGINSIZE-1);
188 #ifdef _NETRC_DEBUG
189 fprintf(stderr, "LOGIN: %s\n", login);
190 #endif
191 }
192 state_login=0;
193 }
194 else if(state_password) {
195 if(state_our_login || !specific_login) {
196 strncpy(password, tok, PASSWORDSIZE-1);
197 #ifdef _NETRC_DEBUG
198 fprintf(stderr, "PASSWORD: %s\n", password);
199 #endif
200 }
201 state_password=0;
202 }
203 else if(Curl_raw_equal("login", tok))
204 state_login=1;
205 else if(Curl_raw_equal("password", tok))
206 state_password=1;
207 else if(Curl_raw_equal("machine", tok)) {
208 /* ok, there's machine here go => */
209 state = HOSTFOUND;
210 state_our_login = FALSE;
211 }
212 break;
213 } /* switch (state) */
214
215 tok = strtok_r(NULL, " \t\n", &tok_buf);
216 } /* while(tok) */
217 } /* while fgets() */
218
219 fclose(file);
220 }
221
222 if(home_alloc)
223 free(home);
224 if(netrc_alloc)
225 free(netrcfile);
226
227 return retcode;
228 }
229
230 #ifdef _NETRC_DEBUG
main(int argc,argv_item_t argv[])231 int main(int argc, argv_item_t argv[])
232 {
233 char login[64]="";
234 char password[64]="";
235
236 if(argc<2)
237 return -1;
238
239 if(0 == ParseNetrc(argv[1], login, password)) {
240 printf("HOST: %s LOGIN: %s PASSWORD: %s\n",
241 argv[1], login, password);
242 }
243 }
244
245 #endif
246