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