Annotation of embedaddon/curl/lib/netrc.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2019, 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: #ifndef CURL_DISABLE_NETRC
                     25: 
                     26: #ifdef HAVE_PWD_H
                     27: #include <pwd.h>
                     28: #endif
                     29: 
                     30: #include <curl/curl.h>
                     31: #include "netrc.h"
                     32: #include "strtok.h"
                     33: #include "strcase.h"
                     34: 
                     35: /* The last 3 #include files should be in this order */
                     36: #include "curl_printf.h"
                     37: #include "curl_memory.h"
                     38: #include "memdebug.h"
                     39: 
                     40: /* Get user and password from .netrc when given a machine name */
                     41: 
                     42: enum host_lookup_state {
                     43:   NOTHING,
                     44:   HOSTFOUND,    /* the 'machine' keyword was found */
                     45:   HOSTVALID     /* this is "our" machine! */
                     46: };
                     47: 
                     48: #define NETRC_FILE_MISSING 1
                     49: #define NETRC_FAILED -1
                     50: #define NETRC_SUCCESS 0
                     51: 
                     52: /*
                     53:  * Returns zero on success.
                     54:  */
                     55: static int parsenetrc(const char *host,
                     56:                       char **loginp,
                     57:                       char **passwordp,
                     58:                       bool *login_changed,
                     59:                       bool *password_changed,
                     60:                       char *netrcfile)
                     61: {
                     62:   FILE *file;
                     63:   int retcode = NETRC_FILE_MISSING;
                     64:   char *login = *loginp;
                     65:   char *password = *passwordp;
                     66:   bool specific_login = (login && *login != 0);
                     67:   bool login_alloc = FALSE;
                     68:   bool password_alloc = FALSE;
                     69:   enum host_lookup_state state = NOTHING;
                     70: 
                     71:   char state_login = 0;      /* Found a login keyword */
                     72:   char state_password = 0;   /* Found a password keyword */
                     73:   int state_our_login = FALSE;  /* With specific_login, found *our* login
                     74:                                    name */
                     75: 
                     76:   DEBUGASSERT(netrcfile);
                     77: 
                     78:   file = fopen(netrcfile, FOPEN_READTEXT);
                     79:   if(file) {
                     80:     char *tok;
                     81:     char *tok_buf;
                     82:     bool done = FALSE;
                     83:     char netrcbuffer[4096];
                     84:     int  netrcbuffsize = (int)sizeof(netrcbuffer);
                     85: 
                     86:     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
                     87:       tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
                     88:       if(tok && *tok == '#')
                     89:         /* treat an initial hash as a comment line */
                     90:         continue;
                     91:       while(tok) {
                     92: 
                     93:         if((login && *login) && (password && *password)) {
                     94:           done = TRUE;
                     95:           break;
                     96:         }
                     97: 
                     98:         switch(state) {
                     99:         case NOTHING:
                    100:           if(strcasecompare("machine", tok)) {
                    101:             /* the next tok is the machine name, this is in itself the
                    102:                delimiter that starts the stuff entered for this machine,
                    103:                after this we need to search for 'login' and
                    104:                'password'. */
                    105:             state = HOSTFOUND;
                    106:           }
                    107:           else if(strcasecompare("default", tok)) {
                    108:             state = HOSTVALID;
                    109:             retcode = NETRC_SUCCESS; /* we did find our host */
                    110:           }
                    111:           break;
                    112:         case HOSTFOUND:
                    113:           if(strcasecompare(host, tok)) {
                    114:             /* and yes, this is our host! */
                    115:             state = HOSTVALID;
                    116:             retcode = NETRC_SUCCESS; /* we did find our host */
                    117:           }
                    118:           else
                    119:             /* not our host */
                    120:             state = NOTHING;
                    121:           break;
                    122:         case HOSTVALID:
                    123:           /* we are now parsing sub-keywords concerning "our" host */
                    124:           if(state_login) {
                    125:             if(specific_login) {
                    126:               state_our_login = strcasecompare(login, tok);
                    127:             }
                    128:             else if(!login || strcmp(login, tok)) {
                    129:               if(login_alloc) {
                    130:                 free(login);
                    131:                 login_alloc = FALSE;
                    132:               }
                    133:               login = strdup(tok);
                    134:               if(!login) {
                    135:                 retcode = NETRC_FAILED; /* allocation failed */
                    136:                 goto out;
                    137:               }
                    138:               login_alloc = TRUE;
                    139:             }
                    140:             state_login = 0;
                    141:           }
                    142:           else if(state_password) {
                    143:             if((state_our_login || !specific_login)
                    144:                 && (!password || strcmp(password, tok))) {
                    145:               if(password_alloc) {
                    146:                 free(password);
                    147:                 password_alloc = FALSE;
                    148:               }
                    149:               password = strdup(tok);
                    150:               if(!password) {
                    151:                 retcode = NETRC_FAILED; /* allocation failed */
                    152:                 goto out;
                    153:               }
                    154:               password_alloc = TRUE;
                    155:             }
                    156:             state_password = 0;
                    157:           }
                    158:           else if(strcasecompare("login", tok))
                    159:             state_login = 1;
                    160:           else if(strcasecompare("password", tok))
                    161:             state_password = 1;
                    162:           else if(strcasecompare("machine", tok)) {
                    163:             /* ok, there's machine here go => */
                    164:             state = HOSTFOUND;
                    165:             state_our_login = FALSE;
                    166:           }
                    167:           break;
                    168:         } /* switch (state) */
                    169: 
                    170:         tok = strtok_r(NULL, " \t\n", &tok_buf);
                    171:       } /* while(tok) */
                    172:     } /* while fgets() */
                    173: 
                    174:     out:
                    175:     if(!retcode) {
                    176:       /* success */
                    177:       *login_changed = FALSE;
                    178:       *password_changed = FALSE;
                    179:       if(login_alloc) {
                    180:         if(*loginp)
                    181:           free(*loginp);
                    182:         *loginp = login;
                    183:         *login_changed = TRUE;
                    184:       }
                    185:       if(password_alloc) {
                    186:         if(*passwordp)
                    187:           free(*passwordp);
                    188:         *passwordp = password;
                    189:         *password_changed = TRUE;
                    190:       }
                    191:     }
                    192:     else {
                    193:       if(login_alloc)
                    194:         free(login);
                    195:       if(password_alloc)
                    196:         free(password);
                    197:     }
                    198:     fclose(file);
                    199:   }
                    200: 
                    201:   return retcode;
                    202: }
                    203: 
                    204: /*
                    205:  * @unittest: 1304
                    206:  *
                    207:  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
                    208:  * in.
                    209:  */
                    210: int Curl_parsenetrc(const char *host,
                    211:                     char **loginp,
                    212:                     char **passwordp,
                    213:                     bool *login_changed,
                    214:                     bool *password_changed,
                    215:                     char *netrcfile)
                    216: {
                    217:   int retcode = 1;
                    218:   char *filealloc = NULL;
                    219: 
                    220:   if(!netrcfile) {
                    221:     char *home = NULL;
                    222:     char *homea = curl_getenv("HOME"); /* portable environment reader */
                    223:     if(homea) {
                    224:       home = homea;
                    225: #if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
                    226:     }
                    227:     else {
                    228:       struct passwd pw, *pw_res;
                    229:       char pwbuf[1024];
                    230:       if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
                    231:          && pw_res) {
                    232:         home = pw.pw_dir;
                    233:       }
                    234: #elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
                    235:     }
                    236:     else {
                    237:       struct passwd *pw;
                    238:       pw = getpwuid(geteuid());
                    239:       if(pw) {
                    240:         home = pw->pw_dir;
                    241:       }
                    242: #endif
                    243:     }
                    244: 
                    245:     if(!home)
                    246:       return retcode; /* no home directory found (or possibly out of
                    247:                          memory) */
                    248: 
                    249:     filealloc = curl_maprintf("%s%s.netrc", home, DIR_CHAR);
                    250:     if(!filealloc) {
                    251:       free(homea);
                    252:       return -1;
                    253:     }
                    254:     retcode = parsenetrc(host, loginp, passwordp, login_changed,
                    255:                          password_changed, filealloc);
                    256:     free(filealloc);
                    257: #ifdef WIN32
                    258:     if(retcode == NETRC_FILE_MISSING) {
                    259:       /* fallback to the old-style "_netrc" file */
                    260:       filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
                    261:       if(!filealloc) {
                    262:         free(homea);
                    263:         return -1;
                    264:       }
                    265:       retcode = parsenetrc(host, loginp, passwordp, login_changed,
                    266:                            password_changed, filealloc);
                    267:       free(filealloc);
                    268:     }
                    269: #endif
                    270:     free(homea);
                    271:   }
                    272:   else
                    273:     retcode = parsenetrc(host, loginp, passwordp, login_changed,
                    274:                          password_changed, netrcfile);
                    275:   return retcode;
                    276: }
                    277: 
                    278: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>