<<< Date Index >>>     <<< Thread Index >>>

[PATCH] Support for reading users and/or passwords from netrc(5)



# 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