15ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/***************************************************************************
25ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                                  _   _ ____  _
35ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *  Project                     ___| | | |  _ \| |
45ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             / __| | | | |_) | |
55ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                            | (__| |_| |  _ <| |___
65ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             \___|\___/|_| \_\_____|
75ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
88f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
95ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * This software is licensed as described in the file COPYING, which
115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * you should have received as part of this distribution. The terms
128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html.
135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * You may opt to use, copy, modify, merge, publish, distribute and/or sell
155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * copies of the Software, and permit persons to whom the Software is
165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * furnished to do so, under the terms of the COPYING file.
175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * KIND, either express or implied.
205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen ***************************************************************************/
225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
23e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h"
245ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef HAVE_PWD_H
265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include <pwd.h>
275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include <curl/curl.h>
305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "netrc.h"
315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "strequal.h"
335ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "strtok.h"
345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "rawstr.h"
355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
368f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo/* The last 3 #include files should be in this order */
378f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo#include "curl_printf.h"
38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_memory.h"
395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "memdebug.h"
405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/* Get user and password from .netrc when given a machine name */
425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
43e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETenum host_lookup_state {
445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  NOTHING,
455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  HOSTFOUND,    /* the 'machine' keyword was found */
46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  HOSTVALID     /* this is "our" machine! */
475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen};
485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*
50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * @unittest: 1304
51e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
52e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * in.
54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */
555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenint Curl_parsenetrc(const char *host,
56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                    char **loginp,
57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                    char **passwordp,
585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen                    char *netrcfile)
595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  FILE *file;
615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int retcode=1;
62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  int specific_login = (*loginp && **loginp != 0);
635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  bool netrc_alloc = FALSE;
64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  enum host_lookup_state state=NOTHING;
655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char state_login=0;      /* Found a login keyword */
675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char state_password=0;   /* Found a password keyword */
685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int state_our_login=FALSE;  /* With specific_login, found *our* login name */
695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define NETRC DOT_CHAR "netrc"
715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(!netrcfile) {
73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    bool home_alloc = FALSE;
74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    char *home = curl_getenv("HOME"); /* portable environment reader */
755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(home) {
765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      home_alloc = TRUE;
77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    else {
80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      struct passwd pw, *pw_res;
81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      char pwbuf[1024];
82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         && pw_res) {
84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        home = strdup(pw.pw_dir);
85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(!home)
86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          return CURLE_OUT_OF_MEMORY;
87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        home_alloc = TRUE;
88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
905ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    else {
925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      struct passwd *pw;
935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      pw= getpwuid(geteuid());
945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      if(pw) {
955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        home = pw->pw_dir;
965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      }
975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
985ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1005ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(!home)
101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      return retcode; /* no home directory found (or possibly out of memory) */
1025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
104e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(home_alloc)
105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      free(home);
1065ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(!netrcfile) {
1075ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      return -1;
1085ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1095ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    netrc_alloc = TRUE;
1105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  file = fopen(netrcfile, FOPEN_READTEXT);
113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(netrc_alloc)
114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    free(netrcfile);
1155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(file) {
1165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    char *tok;
1175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    char *tok_buf;
1185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    bool done=FALSE;
1195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    char netrcbuffer[256];
1205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    int  netrcbuffsize = (int)sizeof(netrcbuffer);
1215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
1235ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
1245ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      while(!done && tok) {
1255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if((*loginp && **loginp) && (*passwordp && **passwordp)) {
1275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          done=TRUE;
1285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          break;
1295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        }
1305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        switch(state) {
1325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        case NOTHING:
1335ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          if(Curl_raw_equal("machine", tok)) {
1345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            /* the next tok is the machine name, this is in itself the
1355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen               delimiter that starts the stuff entered for this machine,
1365ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen               after this we need to search for 'login' and
1375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen               'password'. */
1385ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state=HOSTFOUND;
1395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          }
140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          else if(Curl_raw_equal("default", tok)) {
141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            state=HOSTVALID;
142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            retcode=0; /* we did find our host */
143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
1445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          break;
1455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        case HOSTFOUND:
1465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          if(Curl_raw_equal(host, tok)) {
1475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            /* and yes, this is our host! */
1485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state=HOSTVALID;
1495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            retcode=0; /* we did find our host */
1505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          }
1515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          else
1525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            /* not our host */
1535ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state=NOTHING;
1545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          break;
1555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        case HOSTVALID:
1565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          /* we are now parsing sub-keywords concerning "our" host */
1575ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          if(state_login) {
1585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            if(specific_login) {
159e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              state_our_login = Curl_raw_equal(*loginp, tok);
1605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            }
1615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            else {
162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              free(*loginp);
163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              *loginp = strdup(tok);
164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              if(!*loginp) {
165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                retcode = -1; /* allocation failed */
166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                goto out;
167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              }
1685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            }
1695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state_login=0;
1705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          }
1715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          else if(state_password) {
1725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            if(state_our_login || !specific_login) {
173e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              free(*passwordp);
174e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              *passwordp = strdup(tok);
175e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              if(!*passwordp) {
176e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                retcode = -1; /* allocation failed */
177e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                goto out;
178e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              }
1795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            }
1805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state_password=0;
1815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          }
1825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          else if(Curl_raw_equal("login", tok))
1835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state_login=1;
1845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          else if(Curl_raw_equal("password", tok))
1855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state_password=1;
1865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          else if(Curl_raw_equal("machine", tok)) {
1875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            /* ok, there's machine here go => */
1885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state = HOSTFOUND;
1895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            state_our_login = FALSE;
1905ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          }
1915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen          break;
1925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        } /* switch (state) */
1935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        tok = strtok_r(NULL, " \t\n", &tok_buf);
1955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      } /* while(tok) */
1965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    } /* while fgets() */
1975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
198e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    out:
1995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    fclose(file);
2005ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
2015ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
2025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return retcode;
2035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
204