2c5942afc4dc107a166188f3cff34e64d65a5e33
[platform/upstream/curl.git] / lib / netrc.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 int Curl_parsenetrc(const char *host,
55                     char *login,
56                     char *password,
57                     char *netrcfile)
58 {
59   FILE *file;
60   int retcode=1;
61   int specific_login = (login[0] != 0);
62   char *home = NULL;
63   bool home_alloc = FALSE;
64   bool netrc_alloc = FALSE;
65   enum host_lookup_state state=NOTHING;
66
67   char state_login=0;      /* Found a login keyword */
68   char state_password=0;   /* Found a password keyword */
69   int state_our_login=FALSE;  /* With specific_login, found *our* login name */
70
71 #define NETRC DOT_CHAR "netrc"
72
73   if(!netrcfile) {
74     home = curl_getenv("HOME"); /* portable environment reader */
75     if(home) {
76       home_alloc = TRUE;
77 #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
78     }
79     else {
80       struct passwd *pw;
81       pw= getpwuid(geteuid());
82       if(pw) {
83         home = pw->pw_dir;
84       }
85 #endif
86     }
87
88     if(!home)
89       return -1;
90
91     netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
92     if(!netrcfile) {
93       if(home_alloc)
94         free(home);
95       return -1;
96     }
97     netrc_alloc = TRUE;
98   }
99
100   file = fopen(netrcfile, "r");
101   if(file) {
102     char *tok;
103     char *tok_buf;
104     bool done=FALSE;
105     char netrcbuffer[256];
106     int  netrcbuffsize = (int)sizeof(netrcbuffer);
107
108     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
109       tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
110       while(!done && tok) {
111
112         if(login[0] && password[0]) {
113           done=TRUE;
114           break;
115         }
116
117         switch(state) {
118         case NOTHING:
119           if(Curl_raw_equal("machine", tok)) {
120             /* the next tok is the machine name, this is in itself the
121                delimiter that starts the stuff entered for this machine,
122                after this we need to search for 'login' and
123                'password'. */
124             state=HOSTFOUND;
125           }
126           break;
127         case HOSTFOUND:
128           if(Curl_raw_equal(host, tok)) {
129             /* and yes, this is our host! */
130             state=HOSTVALID;
131             retcode=0; /* we did find our host */
132           }
133           else
134             /* not our host */
135             state=NOTHING;
136           break;
137         case HOSTVALID:
138           /* we are now parsing sub-keywords concerning "our" host */
139           if(state_login) {
140             if(specific_login) {
141               state_our_login = Curl_raw_equal(login, tok);
142             }
143             else {
144               strncpy(login, tok, LOGINSIZE-1);
145             }
146             state_login=0;
147           }
148           else if(state_password) {
149             if(state_our_login || !specific_login) {
150               strncpy(password, tok, PASSWORDSIZE-1);
151             }
152             state_password=0;
153           }
154           else if(Curl_raw_equal("login", tok))
155             state_login=1;
156           else if(Curl_raw_equal("password", tok))
157             state_password=1;
158           else if(Curl_raw_equal("machine", tok)) {
159             /* ok, there's machine here go => */
160             state = HOSTFOUND;
161             state_our_login = FALSE;
162           }
163           break;
164         } /* switch (state) */
165
166         tok = strtok_r(NULL, " \t\n", &tok_buf);
167       } /* while(tok) */
168     } /* while fgets() */
169
170     fclose(file);
171   }
172
173   if(home_alloc)
174     free(home);
175   if(netrc_alloc)
176     free(netrcfile);
177
178   return retcode;
179 }