Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netrc: Implement .netrc parsing #244

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
#ifndef AXEL_CONF_H
#define AXEL_CONF_H

#include "netrc.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 @@ -68,7 +69,7 @@ typedef struct {
int search_threads;
int search_amount;
int search_top;
int use_netrc;
netrc_t *netrc;

unsigned io_timeout;

Expand Down
8 changes: 3 additions & 5 deletions src/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,10 @@ 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_t * netrc;
netrc = netrc_init(conn->conf->netrc_filename, conn->host, conn->user, sizeof(conn->user), conn->pass, sizeof(conn->pass));
netrc_parse(netrc);
if (conn->conf->netrc) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code here shouldn't be conditional, and it should be for all protocols.

We want to support other formats, like authinfo, in the future.

It should be into a separate function, so that refactoring doesn't touch code around it:

conf_auth_setup(conf);

Also auto-login should only happen if we didn't got the credentials from somewhere else, so a check for that is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I will move this code to the conn.c:conn_set() function, as that is the one that deals with parsing URLs and extracting fields like username, password and hostname from them and copying to conn_t. But once parsing is entangled with auth code, I'd rather leave this kind of refactoring to another PR.

netrc_parse(conn->conf->netrc, conn->host, conn->user, sizeof(conn->user), conn->pass, sizeof(conn->pass));
netrc_close(conn->conf->netrc);
printf("host: %s, user: %s, pass: %s\n", conn->host, conn->user, conn->pass);
netrc_close(netrc);
}
if (!ftp_connect(conn->ftp, conn->proto, conn->host, conn->port,
conn->user, conn->pass,
Expand Down
47 changes: 19 additions & 28 deletions src/netrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef struct {
size_t len;
} buffer_t;

static buffer_t tok, save_buf;
static const char *tok_delim = " \t\n";

static size_t
Expand Down Expand Up @@ -143,69 +144,59 @@ netrc_mmap(const char *filename, char **addr)
}

static void
get_creds(netrc_t *netrc, buffer_t last_tok, buffer_t *save_ptr)
get_creds(netrc_t *netrc, char *user, size_t user_len, char *pass, size_t pass_len)
{
buffer_t tok = last_tok;

while (tok.len) {
if (!strncmp("login", tok.data, tok.len)) {
tok = memtok(NULL, 0, tok_delim, save_ptr);
if (tok.len <= netrc->user_len)
strlcpy(netrc->user, tok.data, tok.len+1);
tok = memtok(NULL, 0, tok_delim, &save_buf);
if (tok.len <= user_len)
strlcpy(user, tok.data, tok.len+1);
} else if (!strncmp("password", tok.data, tok.len)) {
tok = memtok(NULL, 0, tok_delim, save_ptr);
if (tok.len <= netrc->pass_len)
strlcpy(netrc->pass, tok.data, tok.len+1);
tok = memtok(NULL, 0, tok_delim, &save_buf);
if (tok.len <= pass_len)
strlcpy(pass, tok.data, tok.len+1);
} else if (!strncmp("machine", tok.data, tok.len) || !strncmp("default", tok.data, tok.len)) {
save_ptr->data -= tok.len;
save_ptr->len += tok.len;
save_buf.data -= tok.len;
save_buf.len += tok.len;
break;
}
tok = memtok(NULL, 0, tok_delim, save_ptr);
tok = memtok(NULL, 0, tok_delim, &save_buf);
}
}

netrc_t *
netrc_init(const char *file, const char *host, char *user, size_t user_len, char *pass, size_t pass_len)
netrc_init(const char *file)
{
netrc_t *netrc;

if (!host || !user || !pass || !user_len || !pass_len)
return NULL;
netrc = calloc(1, sizeof(netrc_t));
if (!netrc)
return NULL;
netrc->file = file;
davidpolverari marked this conversation as resolved.
Show resolved Hide resolved
netrc->host = host;
netrc->user = user;
netrc->user_len = user_len;
netrc->pass = pass;
netrc->pass_len = pass_len;
return netrc;
}

int
davidpolverari marked this conversation as resolved.
Show resolved Hide resolved
netrc_parse(netrc_t *netrc)
netrc_parse(netrc_t *netrc, const char *host, char *user, size_t user_len, char *pass, size_t pass_len)
{
davidpolverari marked this conversation as resolved.
Show resolved Hide resolved
size_t sz;
char *s_addr = NULL;
buffer_t tok, save_ptr;

if (!(sz = netrc_mmap(netrc->file, &s_addr)))
return 0;
tok = memtok(s_addr, sz, tok_delim, &save_ptr);
tok = memtok(s_addr, sz, tok_delim, &save_buf);
while (tok.len) {
if (!strncmp("default", tok.data, tok.len)) {
get_creds(netrc, tok, &save_ptr);
get_creds(netrc, user, user_len, pass, pass_len);
break;
} else if (!strncmp("machine", tok.data, tok.len)) {
tok = memtok(NULL, 0, tok_delim, &save_ptr);
if ((tok.len && !strncmp(netrc->host, tok.data, tok.len))) {
get_creds(netrc, tok, &save_ptr);
tok = memtok(NULL, 0, tok_delim, &save_buf);
if ((tok.len && !strncmp(host, tok.data, tok.len))) {
get_creds(netrc, user, user_len, pass, pass_len);
break;
}
}
tok = memtok(NULL, 0, tok_delim, &save_ptr);
tok = memtok(NULL, 0, tok_delim, &save_buf);
}
munmap(s_addr, sz);
return 1;
Expand Down
9 changes: 2 additions & 7 deletions src/netrc.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,10 @@

typedef struct {
const char *file;
const char *host;
char *user;
size_t user_len;
char *pass;
size_t pass_len;
} netrc_t;

netrc_t *netrc_init(const char *file, const char *host, char *user, size_t user_len, char *pass, size_t pass_len);
int netrc_parse(netrc_t *netrc);
netrc_t *netrc_init(const char *file);
int netrc_parse(netrc_t *netrc, const char *host, char *user, size_t user_len, char *pass, size_t pass_len);
void netrc_close(netrc_t *netrc);

#endif /* AXEL_NETRC_H */
11 changes: 5 additions & 6 deletions src/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,12 @@ main(int argc, char *argv[])
}
break;
case 'R':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's define a negative version, it's necessary for if there's a default in the axel config file. I'm not sure a short version is needed (I've been thinking about removing support for systems not supporting getopt_long anyway).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About negative version of the option, I don't know whether it is a good idea to make .netrc parsing default, as it may break existing users' assumptions/scripts/workflows, etc. What do you think about it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mean to make it the default, but if you have the option on the configuration file, then you need a way to disable it from the command line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll add it.

conf->use_netrc = 1;
if (optarg) {
if (!strlcpy(conf->netrc_filename, optarg,
sizeof(conf->netrc_filename))) {
print_help();
goto free_conf;
{
char *netrc_filename = NULL;
if (optarg) {
netrc_filename = optarg;
}
conf->netrc = netrc_init(netrc_filename);
davidpolverari marked this conversation as resolved.
Show resolved Hide resolved
}
break;
case '6':
Expand Down