# HG changeset patch # User luciano@xxxxxxxxxxxxxxxxxxxxxx # Date 1179848062 -3600 # Node ID 0a3bb46d1d5ee19199f2f7170cfdd16a46cb3553 # Parent 357b7651d6095f5b2e9c5dab1e4cb5c7fb6bc379 Support for reading users and/or passwords from netrc(5) Extended mutt_account_getuser and mutt_account_getpass in account.c with netrc_user and netrc_password for retrieving username and password from ~/.netrc. netrc(5) parsing was added in new files netrc.c and netrc.h. diff -r 357b7651d609 -r 0a3bb46d1d5e Makefile.am --- a/Makefile.am Tue May 22 16:11:15 2007 +0100 +++ b/Makefile.am Tue May 22 16:34:22 2007 +0100 @@ -28,7 +28,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \ rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \ score.c send.c sendlib.c signal.c sort.c \ status.c system.c thread.c charset.c history.c lib.c \ - muttlib.c editmsg.c mbyte.c \ + muttlib.c editmsg.c mbyte.c netrc.c \ url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \ diff -r 357b7651d609 -r 0a3bb46d1d5e account.c --- a/account.c Tue May 22 16:11:15 2007 +0100 +++ b/account.c Tue May 22 16:34:22 2007 +0100 @@ -25,6 +25,7 @@ #include "mutt.h" #include "account.h" #include "url.h" +#include "netrc.h" /* mutt_account_match: compare account info (host/port/user/login) */ int mutt_account_match (const ACCOUNT* a1, const ACCOUNT* a2) @@ -158,6 +159,10 @@ int mutt_account_getuser (ACCOUNT* accou else if ((account->type == M_ACCT_TYPE_POP) && PopUser) strfcpy (account->user, PopUser, sizeof (account->user)); #endif + else if (netrc_user (account->host, + account->user, sizeof (account->user), + account->pass, sizeof (account->pass))) + ; /* prompt (defaults to unix username), copy into account->user */ else { @@ -218,6 +223,11 @@ int mutt_account_getpass (ACCOUNT* accou else if ((account->type == M_ACCT_TYPE_SMTP) && SmtpPass) strfcpy (account->pass, SmtpPass, sizeof (account->pass)); #endif + else if (netrc_password (account->flags & M_ACCT_LOGIN + ? account->login : account->user, + account->host, + account->pass, sizeof (account->pass))) + ; else { snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "), diff -r 357b7651d609 -r 0a3bb46d1d5e netrc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netrc.c Tue May 22 16:34:22 2007 +0100 @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2007 Luciano Rocha <strange@xxxxxx> + * + * 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. + * + * 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(5) parsing support */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +/* for isspace(c) */ +#include <ctype.h> + +#include "mutt.h" +#include "netrc.h" + +/* token types */ +enum +{ + M_NETRC_TOK_DEFAULT, + M_NETRC_TOK_MACHINE, + M_NETRC_TOK_LOGIN, + M_NETRC_TOK_PASSWORD, + M_NETRC_TOK_ACCOUNT, + M_NETRC_TOK_MACRO, + M_NETRC_TOK_UNKNOWN +}; + +/* tokens and their values */ +typedef struct { + int type; + char *value1; + int len1; + char *value2; + int len2; +} TOKEN; + +/* open netrc */ +static FILE *netrc_open (void) +{ + char path[_POSIX_PATH_MAX]; + + snprintf (path, sizeof (path), "%s/.netrc", NONULL(Homedir)); + return fopen (path, "r"); +} + +/* clean tok structure and free any alloced data */ +static void netrc_free_tok (TOKEN *tok) +{ + if (tok->value1) + free (tok->value1); + if (tok->value2) + free (tok->value2); + tok->value1 = tok->value2 = NULL; + tok->len1 = tok->len2 = 0; +} + +/* read next token from netrc and its values */ +static int netrc_next_tok (FILE *fp, TOKEN *tok) +{ + char token[40]; + char value[256]; + int c, i; + + netrc_free_tok (tok); + + /* skip whitespace */ + while ((c = getc (fp)) != EOF && isspace (c)); + if (c == EOF) + return 0; + + /* get token (text till next whitespace) */ + token[0] = (char) c; + i = 1; + while ((c = getc (fp)) != EOF && !isspace (c) + && i < (sizeof token - 1)) + token[i++] = (char) c; + + /* abort if EOF or whould exceed token space */ + if (c == EOF || i == (sizeof token - 1)) + return 0; + + token[i++] = '\0'; + + /* "default" is special, as it doesn't have a value */ + if (!ascii_strcasecmp ("default", token)) + { + tok->type = M_NETRC_TOK_DEFAULT; + return 1; + } + + /* has a value, read it */ + + /* skip whitespace */ + while ((c = getc (fp)) != EOF && isspace (c)); + + /* no value found if EOF */ + if (c == EOF) + return 0; + + /* get value (text till next whitespace) */ + value[0] = (char) c; + i = 1; + while ((c = getc (fp)) != EOF && !isspace (c) + && i < (sizeof value - 1)) + value[i++] = (char) c; + + /* abort if EOF or whould exceed value space */ + if (c == EOF || i == (sizeof value - 1)) + return 0; + value[i++] = '\0'; + + tok->value1 = safe_strdup (value); + tok->len1 = i; + + if (!ascii_strcasecmp ("machine", token)) + tok->type = M_NETRC_TOK_MACHINE; + else if (!ascii_strcasecmp ("login", token)) + tok->type = M_NETRC_TOK_LOGIN; + else if (!ascii_strcasecmp ("password", token)) + tok->type = M_NETRC_TOK_PASSWORD; + else if (!ascii_strcasecmp ("account", token)) + tok->type = M_NETRC_TOK_ACCOUNT; + else if (!ascii_strcasecmp ("macdef", token)) + tok->type = M_NETRC_TOK_MACRO; + else + tok->type = M_NETRC_TOK_UNKNOWN; + + /* "macdef" next lines till EOF or empty line */ + if (tok->type == M_NETRC_TOK_MACRO) + { + char *p = NULL; + int l = 0; + + /* skip to end of line */ + while (c != EOF && c != '\n') + c = getc (fp); + + /* while not an empty line, add to value2 */ + while (fgets (value, sizeof value, fp)) + { + for (i = 0; value[i] && isspace (value[i]); i++); + if (value[i] == '\0') + /* stopped at '\0': empty line */ + break; + + /* length of string, excluding \0 */ + i = i + strlen (value + i); + + /* extend buffer by i and copy new content */ + safe_realloc (&p, l + i + 1); + memcpy (p + l, value, i + 1); + l += i; + } + tok->value2 = p; + tok->len2 = l + 1; /* include terminating '\0' */ + } + return 1; +} + +/* get password for user @ host from $HOME/.netrc: + * returns true if found, and the password argument is updated with + * the value */ +int netrc_password (const char *login, const char *host, + char *password, size_t length) +{ + TOKEN tok; + FILE *nr; + char *user = NULL; + int in_host = 0; + int found = 0; + + nr = netrc_open (); + if (!nr) return 0; + + memset (&tok, 0, sizeof tok); + + while (netrc_next_tok (nr, &tok)) + { + /* search for default or "machine" == host */ + if (tok.type == M_NETRC_TOK_DEFAULT + || (tok.type == M_NETRC_TOK_MACHINE + && !ascii_strcasecmp (tok.value1, + host))) + { + in_host = 1; + if (user) + { + free (user); + user = NULL; + } + } + else if (tok.type == M_NETRC_TOK_MACHINE) + in_host = 0; + else if (!in_host) + /* ignore tokens for other hosts */ + ; + else if (tok.type == M_NETRC_TOK_LOGIN) + { + /* copy value of user */ + if (user) free (user); + user = safe_strdup (tok.value1); + } + else if (tok.type == M_NETRC_TOK_PASSWORD + && /* password valid if user undefined or + user defined to value of login */ + (!user || !strcmp (login, user))) + { + /* check if password fits in buffer */ + if (tok.len1 > length) + break; + memcpy (password, tok.value1, tok.len1); + found = 1; + break; + } + } + + /* clean up */ + netrc_free_tok (&tok); + if (user) free (user); + fclose (nr); + + return found; +} + +/* get login and password for host from $HOME/.netrc: + * returns true if found, updates arguments if not pointing to NULL */ +int netrc_user (const char *host, + char *login, size_t login_length, + char *password, size_t password_length) +{ + TOKEN tok; + FILE *nr; + char *user = NULL; + int in_host = 0; + int i; + int found = 0; + + nr = netrc_open (); + if (!nr) return 0; + + memset (&tok, 0, sizeof tok); + + while (netrc_next_tok (nr, &tok)) + { + /* search for default or "machine" == host */ + if (tok.type == M_NETRC_TOK_DEFAULT + || (tok.type == M_NETRC_TOK_MACHINE + && !ascii_strcasecmp (tok.value1, + host))) + { + in_host = 1; + if (user) + { + free (user); + user = NULL; + } + } + else if (tok.type == M_NETRC_TOK_MACHINE) + in_host = 0; + else if (!in_host) + /* ignore tokens for other hosts */ + ; + else if (tok.type == M_NETRC_TOK_LOGIN) + { + /* copy value of user */ + if (user) free (user); + user = safe_strdup (tok.value1); + } + else if (tok.type == M_NETRC_TOK_PASSWORD + && /* password valid if any user defined */ + user) + { + /* check if password fits in buffer */ + if (tok.len1 > password_length) + break; + + /* check if login fits in buffer */ + i = strlen (user) + 1; + if (i > login_length) + break; + + memcpy (password, tok.value1, tok.len1); + memcpy (login, user, i); + + found = 1; + break; + } + } + + /* if no user + password found, check only user */ + if (!found && user) + { + i = strlen (user) + 1; + if (i <= login_length) + { + memcpy (login, user, i); + found = 1; + } + } + + /* clean up */ + netrc_free_tok (&tok); + if (user) free (user); + fclose (nr); + + return found; +} diff -r 357b7651d609 -r 0a3bb46d1d5e netrc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netrc.h Tue May 22 16:34:22 2007 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007 Luciano Rocha <strange@xxxxxx> + * + * 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. + * + * 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(5) parsing support */ + +#ifndef _MUTT_NETRC_H_ +#define _MUTT_NETRC_H_ 1 + +/* get password for user login @ host. + * returns true when found and populates password argument to length limit + * (including terminating \0) */ +int netrc_password (const char *login, const char *host, + char *password, size_t length); + +/* get login and password for host. + * returns true when found and populates both login and password argument to + * their lengths limit (including terminating \0), if not pointing to NULL */ +int netrc_user (const char *host, + char *login, size_t login_length, + char *password, size_t password_length); + +#endif /* _MUTT_NETRC_H_ */
Attachment:
pgpM4d2lxAmue.pgp
Description: PGP signature