Skip to content
Snippets Groups Projects
netrc.c 6.06 KiB
Newer Older
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
Daniel Stenberg's avatar
Daniel Stenberg committed
 *                             \___|\___/|_| \_\_____|
 *
Yang Tse's avatar
 
Yang Tse committed
 * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
Daniel Stenberg's avatar
Daniel Stenberg committed
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
Daniel Stenberg's avatar
Daniel Stenberg committed
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
Daniel Stenberg's avatar
Daniel Stenberg committed
 *
Daniel Stenberg's avatar
Daniel Stenberg committed
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
Daniel Stenberg's avatar
Daniel Stenberg committed
 *
 ***************************************************************************/
Daniel Stenberg's avatar
Daniel Stenberg committed

Daniel Stenberg's avatar
Daniel Stenberg committed
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed
#include <unixlib.h>
#endif
#include <curl/curl.h>
#include "strequal.h"
#include "strtok.h"
#include "curl_memory.h"
Daniel Stenberg's avatar
Daniel Stenberg committed

#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>

/* The last #include file should be: */
#include "memdebug.h"

Daniel Stenberg's avatar
Daniel Stenberg committed
/* Get user and password from .netrc when given a machine name */

enum host_lookup_state {
Daniel Stenberg's avatar
Daniel Stenberg committed
  NOTHING,
  HOSTFOUND,    /* the 'machine' keyword was found */
  HOSTCOMPLETE, /* the machine name following the keyword was found too */
  HOSTVALID,    /* this is "our" machine! */

  HOSTEND /* LAST enum */
};

/* make sure we have room for at least this size: */
#define LOGINSIZE 64
#define PASSWORDSIZE 64

/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
Dan Fandrich's avatar
Dan Fandrich committed
int Curl_parsenetrc(const char *host,
                    char *password,
                    char *netrcfile)
Daniel Stenberg's avatar
Daniel Stenberg committed
{
  FILE *file;
  int retcode=1;
  int specific_login = (login[0] != 0);
  bool home_alloc = FALSE;
  bool netrc_alloc = FALSE;
  enum host_lookup_state state=NOTHING;
Daniel Stenberg's avatar
Daniel Stenberg committed

  char state_login=0;      /* Found a login keyword */
  char state_password=0;   /* Found a password keyword */
  int state_our_login=FALSE;  /* With specific_login, found *our* login name */
Daniel Stenberg's avatar
Daniel Stenberg committed

#define NETRC DOT_CHAR "netrc"

#ifdef DEBUGBUILD
  {
    /* This is a hack to allow testing.
     * If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
     * then it's the path to a substitute .netrc for testing purposes *only* */

    char *override = curl_getenv("CURL_DEBUG_NETRC");

Daniel Stenberg's avatar
Daniel Stenberg committed
    if(override) {
      fprintf(stderr, "NETRC: overridden " NETRC " file: %s\n", override);
      netrcfile = override;
      netrc_alloc = TRUE;
#endif /* DEBUGBUILD */
  if(!netrcfile) {
    home = curl_getenv("HOME"); /* portable environment reader */
    if(home) {
      home_alloc = TRUE;
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
    }
    else {
      struct passwd *pw;
      pw= getpwuid(geteuid());
Daniel Stenberg's avatar
Daniel Stenberg committed
      if(pw) {
        home = decc_translate_vms(pw->pw_dir);
#else
#endif
    netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
    if(!netrcfile) {
      if(home_alloc)
        free(home);
      return -1;
    }
    netrc_alloc = TRUE;
  }
  file = fopen(netrcfile, "r");
Daniel Stenberg's avatar
Daniel Stenberg committed
  if(file) {
    char *tok;
    char *tok_buf;
    bool done=FALSE;
    char netrcbuffer[256];
    int  netrcbuffsize = (int)sizeof(netrcbuffer);
Yang Tse's avatar
 
Yang Tse committed

    while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
      tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
      while(!done && tok) {
Daniel Stenberg's avatar
Daniel Stenberg committed
        if(login[0] && password[0]) {
        switch(state) {
        case NOTHING:
            /* the next tok is the machine name, this is in itself the
               delimiter that starts the stuff entered for this machine,
               after this we need to search for 'login' and
               'password'. */
            state=HOSTFOUND;
          }
          break;
        case HOSTFOUND:
            /* and yes, this is our host! */
            state=HOSTVALID;
Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef _NETRC_DEBUG
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
            retcode=0; /* we did find our host */
          }
          else
            /* not our host */
            state=NOTHING;
          break;
        case HOSTVALID:
          /* we are now parsing sub-keywords concerning "our" host */
          if(state_login) {
Daniel Stenberg's avatar
Daniel Stenberg committed
            if(specific_login) {
              state_our_login = Curl_raw_equal(login, tok);
              strncpy(login, tok, LOGINSIZE-1);
Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef _NETRC_DEBUG
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
            state_login=0;
          }
          else if(state_password) {
Daniel Stenberg's avatar
Daniel Stenberg committed
            if(state_our_login || !specific_login) {
              strncpy(password, tok, PASSWORDSIZE-1);
#ifdef _NETRC_DEBUG
              fprintf(stderr, "PASSWORD: %s\n", password);
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
          else if(Curl_raw_equal("machine", tok)) {
            /* ok, there's machine here go => */
            state = HOSTFOUND;
        case HOSTCOMPLETE:
        case HOSTEND:
            /* Should not be reached. */
            DEBUGASSERT(0);
        } /* switch (state) */
        tok = strtok_r(NULL, " \t\n", &tok_buf);
Daniel Stenberg's avatar
Daniel Stenberg committed
      } /* while(tok) */
Daniel Stenberg's avatar
Daniel Stenberg committed
    } /* while fgets() */

    fclose(file);
  }

  if(home_alloc)
  if(netrc_alloc)
    free(netrcfile);
Daniel Stenberg's avatar
Daniel Stenberg committed
  return retcode;
}