File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / netrc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>