smtp: use the upload buffer size for scratch buffer malloc
[platform/upstream/curl.git] / lib / netrc.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 https://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 #include "strtok.h"
32 #include "strcase.h"
33
34 /* The last 3 #include files should be in this order */
35 #include "curl_printf.h"
36 #include "curl_memory.h"
37 #include "memdebug.h"
38
39 /* Get user and password from .netrc when given a machine name */
40
41 enum host_lookup_state {
42   NOTHING,
43   HOSTFOUND,    /* the 'machine' keyword was found */
44   HOSTVALID     /* this is "our" machine! */
45 };
46
47 /*
48  * @unittest: 1304
49  *
50  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
51  * in.
52  */
53 int Curl_parsenetrc(const char *host,
54                     char **loginp,
55                     char **passwordp,
56                     char *netrcfile)
57 {
58   FILE *file;
59   int retcode = 1;
60   int specific_login = (*loginp && **loginp != 0);
61   bool netrc_alloc = FALSE;
62   enum host_lookup_state state = NOTHING;
63
64   char state_login = 0;      /* Found a login keyword */
65   char state_password = 0;   /* Found a password keyword */
66   int state_our_login = FALSE;  /* With specific_login, found *our* login
67                                    name */
68
69 #define NETRC DOT_CHAR "netrc"
70
71   if(!netrcfile) {
72     bool home_alloc = FALSE;
73     char *home = curl_getenv("HOME"); /* portable environment reader */
74     if(home) {
75       home_alloc = TRUE;
76 #if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
77     }
78     else {
79       struct passwd pw, *pw_res;
80       char pwbuf[1024];
81       if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
82          && pw_res) {
83         home = strdup(pw.pw_dir);
84         if(!home)
85           return CURLE_OUT_OF_MEMORY;
86         home_alloc = TRUE;
87       }
88 #elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
89     }
90     else {
91       struct passwd *pw;
92       pw = getpwuid(geteuid());
93       if(pw) {
94         home = pw->pw_dir;
95       }
96 #endif
97     }
98
99     if(!home)
100       return retcode; /* no home directory found (or possibly out of memory) */
101
102     netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
103     if(home_alloc)
104       free(home);
105     if(!netrcfile) {
106       return -1;
107     }
108     netrc_alloc = TRUE;
109   }
110
111   file = fopen(netrcfile, FOPEN_READTEXT);
112   if(netrc_alloc)
113     free(netrcfile);
114   if(file) {
115     char *tok;
116     char *tok_buf;
117     bool done = FALSE;
118     char netrcbuffer[256];
119     int  netrcbuffsize = (int)sizeof(netrcbuffer);
120
121     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
122       tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
123       if(tok && *tok == '#')
124         /* treat an initial hash as a comment line */
125         continue;
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(strcasecompare("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           else if(strcasecompare("default", tok)) {
143             state = HOSTVALID;
144             retcode = 0; /* we did find our host */
145           }
146           break;
147         case HOSTFOUND:
148           if(strcasecompare(host, tok)) {
149             /* and yes, this is our host! */
150             state = HOSTVALID;
151             retcode = 0; /* we did find our host */
152           }
153           else
154             /* not our host */
155             state = NOTHING;
156           break;
157         case HOSTVALID:
158           /* we are now parsing sub-keywords concerning "our" host */
159           if(state_login) {
160             if(specific_login) {
161               state_our_login = strcasecompare(*loginp, tok);
162             }
163             else {
164               free(*loginp);
165               *loginp = strdup(tok);
166               if(!*loginp) {
167                 retcode = -1; /* allocation failed */
168                 goto out;
169               }
170             }
171             state_login = 0;
172           }
173           else if(state_password) {
174             if(state_our_login || !specific_login) {
175               free(*passwordp);
176               *passwordp = strdup(tok);
177               if(!*passwordp) {
178                 retcode = -1; /* allocation failed */
179                 goto out;
180               }
181             }
182             state_password = 0;
183           }
184           else if(strcasecompare("login", tok))
185             state_login = 1;
186           else if(strcasecompare("password", tok))
187             state_password = 1;
188           else if(strcasecompare("machine", tok)) {
189             /* ok, there's machine here go => */
190             state = HOSTFOUND;
191             state_our_login = FALSE;
192           }
193           break;
194         } /* switch (state) */
195
196         tok = strtok_r(NULL, " \t\n", &tok_buf);
197       } /* while(tok) */
198     } /* while fgets() */
199
200     out:
201     fclose(file);
202   }
203
204   return retcode;
205 }