Blame src/netrc.cc

Packit 8f70b4
/*
Packit 8f70b4
 * lftp - file transfer program
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (c) 1996-2012 by Alexander V. Lukyanov (lav@yars.free.net)
Packit 8f70b4
 *
Packit 8f70b4
 * This program is free software; you can redistribute it and/or modify
Packit 8f70b4
 * it under the terms of the GNU General Public License as published by
Packit 8f70b4
 * the Free Software Foundation; either version 3 of the License, or
Packit 8f70b4
 * (at your option) any later version.
Packit 8f70b4
 *
Packit 8f70b4
 * This program is distributed in the hope that it will be useful,
Packit 8f70b4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
 * GNU General Public License for more details.
Packit 8f70b4
 *
Packit 8f70b4
 * You should have received a copy of the GNU General Public License
Packit 8f70b4
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#include <config.h>
Packit 8f70b4
Packit 8f70b4
#include "trio.h"
Packit 8f70b4
#include <stdlib.h>
Packit 8f70b4
#include <errno.h>
Packit 8f70b4
#include "xstring.h"
Packit 8f70b4
#include "netrc.h"
Packit 8f70b4
#include "log.h"
Packit 8f70b4
Packit 8f70b4
static bool comment(const char *s, FILE *f)
Packit 8f70b4
{
Packit 8f70b4
   if(s[0]!='#')
Packit 8f70b4
      return false;
Packit 8f70b4
   // skip entire line
Packit 8f70b4
   for(;;)
Packit 8f70b4
   {
Packit 8f70b4
      int ch=getc(f);
Packit 8f70b4
      if(ch==EOF || ch=='\n')
Packit 8f70b4
	 break;
Packit 8f70b4
   }
Packit 8f70b4
   return true;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
NetRC::Entry *NetRC::LookupHost(const char *h,const char *u)
Packit 8f70b4
{
Packit 8f70b4
   char str[256];
Packit 8f70b4
   char chost[256]="";
Packit 8f70b4
   char cuser[256]="";
Packit 8f70b4
   char cpass[256]="";
Packit 8f70b4
   char cacct[256]="";
Packit 8f70b4
Packit 8f70b4
   const char *const home=getenv("HOME");
Packit 8f70b4
   if(!home)
Packit 8f70b4
      return 0;
Packit 8f70b4
Packit 8f70b4
   const char *const netrc=xstring::cat(home,"/.netrc",NULL);
Packit 8f70b4
   FILE *f=fopen(netrc,"r");
Packit 8f70b4
   if(f==NULL)
Packit 8f70b4
   {
Packit 8f70b4
      Log::global->Format(10,"notice: cannot open %s: %s\n",netrc,strerror(errno));
Packit 8f70b4
      return NULL;
Packit 8f70b4
   }
Packit 8f70b4
Packit 8f70b4
   bool host_found=false;
Packit 8f70b4
   bool user_found=false;
Packit 8f70b4
   while(fscanf(f,"%255s",str)==1)
Packit 8f70b4
   {
Packit 8f70b4
      if(comment(str,f))
Packit 8f70b4
	 continue;
Packit 8f70b4
      if(!strcmp(str,"macdef"))
Packit 8f70b4
      {
Packit 8f70b4
	 // currently macdef is ignored
Packit 8f70b4
	 if(fgets(str,255,f)==0)
Packit 8f70b4
	    break;
Packit 8f70b4
	 for(;;)
Packit 8f70b4
	 {
Packit 8f70b4
	    if(fgets(str,255,f)==0)
Packit 8f70b4
	       break;
Packit 8f70b4
	    if(str[strspn(str," \t\n")]==0) // macdef ends with empty line
Packit 8f70b4
	       break;
Packit 8f70b4
	 }
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
      if(!strcmp(str,"default"))
Packit 8f70b4
      {
Packit 8f70b4
	 strcpy(chost,""); // ignore the default
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
      if(!strcmp(str,"machine"))
Packit 8f70b4
      {
Packit 8f70b4
	 if(host_found && user_found)
Packit 8f70b4
	    break;
Packit 8f70b4
	 if(fscanf(f,"%255s",str)!=1)
Packit 8f70b4
	    break;
Packit 8f70b4
	 strcpy(chost,str);
Packit 8f70b4
	 // reset data for new machine.
Packit 8f70b4
	 cuser[0]=0;
Packit 8f70b4
	 cpass[0]=0;
Packit 8f70b4
	 cacct[0]=0;
Packit 8f70b4
	 host_found=!strcasecmp(chost,h);
Packit 8f70b4
	 user_found=false;
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
      if(!strcmp(str,"login"))
Packit 8f70b4
      {
Packit 8f70b4
	 if(fscanf(f,"%255s",str)!=1)
Packit 8f70b4
	    break;
Packit 8f70b4
	 if(strcasecmp(chost,h))
Packit 8f70b4
	    continue;
Packit 8f70b4
	 strcpy(cuser,str);
Packit 8f70b4
	 cpass[0]=0;
Packit 8f70b4
	 cacct[0]=0;
Packit 8f70b4
	 user_found=(!u || !strcasecmp(cuser,u));
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
      if(!strcmp(str,"password"))
Packit 8f70b4
      {
Packit 8f70b4
	 if(fscanf(f,"%255s",str)!=1)
Packit 8f70b4
	    break;
Packit 8f70b4
	 if(strcasecmp(chost,h) || (u && strcasecmp(cuser,u)) || cpass[0])
Packit 8f70b4
	    continue;
Packit 8f70b4
	 strcpy(cpass,str);
Packit 8f70b4
	 for(char *s=cpass; *s; s++)
Packit 8f70b4
	 {
Packit 8f70b4
	    if(*s=='\\' && s[1]>='0' && s[1]<'8')
Packit 8f70b4
	    {
Packit 8f70b4
	       int ch=0;
Packit 8f70b4
	       int n=0;
Packit 8f70b4
	       if(sscanf(s+1,"%3o%n",&ch,&n)!=1)
Packit 8f70b4
		  continue;
Packit 8f70b4
	       if(ch==0)
Packit 8f70b4
		  continue;
Packit 8f70b4
	       *s=ch;
Packit 8f70b4
	       memmove(s+1,s+1+n,strlen(s+1+n)+1);
Packit 8f70b4
	    }
Packit 8f70b4
	 }
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
      if(!strcmp(str,"account"))
Packit 8f70b4
      {
Packit 8f70b4
	 if(fscanf(f,"%255s",str)!=1)
Packit 8f70b4
	    break;
Packit 8f70b4
	 if(strcasecmp(chost,h) || (u && strcasecmp(cuser,u)) || cacct[0])
Packit 8f70b4
	    continue;
Packit 8f70b4
	 strcpy(cacct,str);
Packit 8f70b4
	 continue;
Packit 8f70b4
      }
Packit 8f70b4
   }
Packit 8f70b4
   fclose(f);
Packit 8f70b4
   if(host_found && user_found)
Packit 8f70b4
   {
Packit 8f70b4
      Log::global->Format(10,"found netrc entry: host=%s, user=%s, pass=%s, acct=%s\n",h,cuser,cpass,cacct);
Packit 8f70b4
      return new Entry(h,cuser[0]?cuser:0,cpass[0]?cpass:0,cacct[0]?cacct:0);
Packit 8f70b4
   }
Packit 8f70b4
   return 0;
Packit 8f70b4
}