Skip to content

Commit

Permalink
netrc: Implement .netrc parsing
Browse files Browse the repository at this point in the history
This implementation parses the $HOME/.netrc (or a file specified by the
user) through the `--netrc[=file]` or `-R[file]` options.

It uses a simple FSM in order to parse the file and find the credentials
corresponding to the FTP host, or uses the "default" entry otherwise,
if any, according to the specification found on [1]. Tokens not
applicable to axel usage were not considered.

[1] https://docs.oracle.com/cd/E19455-01/806-0633/6j9vn6q5f/index.html

Closes: axel-download-accelerator#116

Signed-off-by: David Polverari <[email protected]>
  • Loading branch information
davidpolverari committed Oct 18, 2019
1 parent c3473c2 commit ea153e9
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ axel_SOURCES = \
src/ftp.h \
src/http.c \
src/http.h \
src/netrc.c \
src/netrc.h \
src/search.c \
src/search.h \
src/ssl.c \
Expand Down
2 changes: 2 additions & 0 deletions src/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#define AXEL_CONF_H

typedef struct {
char netrc_filename[MAX_STRING];
char default_filename[MAX_STRING];
char http_proxy[MAX_STRING];
char no_proxy[MAX_STRING];
Expand All @@ -67,6 +68,7 @@ typedef struct {
int search_threads;
int search_amount;
int search_top;
int use_netrc;

unsigned io_timeout;

Expand Down
3 changes: 3 additions & 0 deletions src/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
/* Connection stuff */

#include "axel.h"
#include "netrc.h"

/**
* Convert an URL to a conn_t structure.
Expand Down Expand Up @@ -253,6 +254,8 @@ conn_init(conn_t *conn)
conn->ftp->local_if = conn->local_if;
conn->ftp->ftp_mode = FTP_PASSIVE;
conn->ftp->tcp.ai_family = conn->conf->ai_family;
if (conn->conf->use_netrc)
netrc_parse(conn);
if (!ftp_connect(conn->ftp, conn->proto, conn->host, conn->port,
conn->user, conn->pass,
conn->conf->io_timeout)) {
Expand Down
114 changes: 114 additions & 0 deletions src/netrc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
Axel -- A lighter download accelerator for Linux and other Unices
Copyright 2019 David da Silva Polverari
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
individual source file, and distribute linked combinations including
the two.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the
file(s), but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version. If you delete
this exception statement from all source files in the program, then
also delete it here.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/* .netrc parsing implementation */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "axel.h"
#include "netrc.h"

enum lookup_state {
NOTHING,
DEFAULT,
MACHINE,
HOST_ENTRY,
LOGIN,
PASSWORD
};

void
netrc_parse(conn_t *conn)
{
FILE *fp;
bool found = false;
char *home;
char *tok, *ntok;
char line[MAX_STRING];
char const *delims = " \t\n";
enum lookup_state state = NOTHING;

if (conn->conf->netrc_filename[0] == '\0') {
home = getenv("HOME");
snprintf(conn->conf->netrc_filename, MAX_STRING, "%s/.netrc", home);
}
if ((fp = fopen(conn->conf->netrc_filename, "r")) == NULL)
return;
while (!found && fgets(line, MAX_STRING, fp)) {
tok = strtok_r(line, delims, &ntok);
if (tok && *tok == '#')
continue;
while (tok != NULL) {
switch (state) {
case NOTHING:
if (!strcmp("machine", tok)) {
state = MACHINE;
} else if (!strcmp("default", tok)) {
state = DEFAULT;
}
break;
case MACHINE:
if (!strcmp(conn->host, tok)) {
state = HOST_ENTRY;
} else {
state = NOTHING;
}
break;
case DEFAULT:
state = HOST_ENTRY;
// fall through
case HOST_ENTRY:
if (!strcmp("login", tok)) {
state = LOGIN;
} else if (!strcmp("password", tok)) {
state = PASSWORD;
}
break;
case LOGIN:
strcpy(conn->user, tok);
state = HOST_ENTRY;
break;
case PASSWORD:
strcpy(conn->pass, tok);
found = true;
break;
default:
break;
}
tok = strtok_r(NULL, delims, &ntok);
}
}
}
42 changes: 42 additions & 0 deletions src/netrc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Axel -- A lighter download accelerator for Linux and other Unices
Copyright 2019 David da Silva Polverari
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
individual source file, and distribute linked combinations including
the two.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the
file(s), but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version. If you delete
this exception statement from all source files in the program, then
also delete it here.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/* .netrc parsing include file */

#ifndef AXEL_NETRC_H
#define AXEL_NETRC_H

void netrc_parse(conn_t *conn);

#endif /* AXEL_NETRC_H */
14 changes: 13 additions & 1 deletion src/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static struct option axel_options[] = {
{"max-redirect", 1, NULL, MAX_REDIR_OPT},
{"output", 1, NULL, 'o'},
{"search", 2, NULL, 'S'},
{"netrc", 2, NULL, 'R'},
{"ipv4", 0, NULL, '4'},
{"ipv6", 0, NULL, '6'},
{"no-proxy", 0, NULL, 'N'},
Expand Down Expand Up @@ -117,7 +118,7 @@ main(int argc, char *argv[])
j = -1;
while (1) {
int option = getopt_long(argc, argv,
"s:n:o:S::46NqvhVakcH:U:T:",
"s:n:o:S::R::46NqvhVakcH:U:T:",
axel_options, NULL);
if (option == -1)
break;
Expand Down Expand Up @@ -161,6 +162,15 @@ main(int argc, char *argv[])
}
}
break;
case 'R':
conf->use_netrc = 1;
if (optarg) {
if (!sscanf(optarg, "%s", conf->netrc_filename)) {
print_help();
goto free_conf;
}
}
break;
case '6':
conf->ai_family = AF_INET6;
break;
Expand Down Expand Up @@ -659,6 +669,7 @@ print_help(void)
"-n x\tSpecify maximum number of connections\n"
"-o f\tSpecify local output file\n"
"-S[n]\tSearch for mirrors and download from n servers\n"
"-R[file]\tRetrieve credentials from $HOME/.netrc file or filename\n"
"-4\tUse the IPv4 protocol\n"
"-6\tUse the IPv6 protocol\n"
"-H x\tAdd HTTP header string\n"
Expand All @@ -682,6 +693,7 @@ print_help(void)
"--max-redirect=x\t\tSpecify maximum number of redirections\n"
"--output=f\t\t-o f\tSpecify local output file\n"
"--search[=n]\t\t-S[n]\tSearch for mirrors and download from n servers\n"
"--netrc[=file]\t\t-R[file]\tRetrieve credentials from $HOME/.netrc file or filename\n"
"--ipv4\t\t\t-4\tUse the IPv4 protocol\n"
"--ipv6\t\t\t-6\tUse the IPv6 protocol\n"
"--header=x\t\t-H x\tAdd HTTP header string\n"
Expand Down

0 comments on commit ea153e9

Please sign in to comment.