"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.5/src/password.c" (12 Jan 2019, 6489 Bytes) of package /linux/privat/msmtp-1.8.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "password.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * password.c
    3  *
    4  * This file is part of msmtp, an SMTP client, and of mpop, a POP3 client.
    5  *
    6  * Copyright (C) 2019  Martin Lambers <marlam@marlam.de>
    7  * Jay Soffian <jaysoffian@gmail.com> (Mac OS X keychain support)
    8  *
    9  *   This program is free software; you can redistribute it and/or modify
   10  *   it under the terms of the GNU General Public License as published by
   11  *   the Free Software Foundation; either version 3 of the License, or
   12  *   (at your option) any later version.
   13  *
   14  *   This program is distributed in the hope that it will be useful,
   15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *   GNU General Public License for more details.
   18  *
   19  *   You should have received a copy of the GNU General Public License
   20  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   21  */
   22 
   23 #ifdef HAVE_CONFIG_H
   24 # include "config.h"
   25 #endif
   26 
   27 #include <stdio.h>
   28 #include <stdlib.h>
   29 #include <unistd.h>
   30 #ifdef HAVE_LIBSECRET
   31 # include <libsecret/secret.h>
   32 #endif
   33 #ifdef HAVE_MACOSXKEYRING
   34 # include <Security/Security.h>
   35 #endif
   36 
   37 #include "gettext.h"
   38 #define _(string) gettext(string)
   39 
   40 #include "netrc.h"
   41 #include "tools.h"
   42 #include "xalloc.h"
   43 #include "password.h"
   44 
   45 #ifdef W32_NATIVE
   46 #define SYSNETRCFILE    "netrc.txt"
   47 #define USERNETRCFILE   "netrc.txt"
   48 #else /* UNIX */
   49 #define SYSNETRCFILE    "netrc"
   50 #define USERNETRCFILE   ".netrc"
   51 #endif
   52 
   53 
   54 /*
   55  * password_get()
   56  *
   57  * see password.h
   58  */
   59 
   60 #ifdef HAVE_LIBSECRET
   61 static const SecretSchema *get_schema(void)
   62 {
   63     static const SecretSchema schema = {
   64         "de.marlam." PACKAGE_NAME ".password", SECRET_SCHEMA_DONT_MATCH_NAME,
   65         {
   66             {  "host", SECRET_SCHEMA_ATTRIBUTE_STRING },
   67             {  "service", SECRET_SCHEMA_ATTRIBUTE_STRING },
   68             {  "user", SECRET_SCHEMA_ATTRIBUTE_STRING },
   69             {  "NULL", 0 },
   70         }
   71     };
   72     return &schema;
   73 }
   74 static const char *service_string(password_service_t service)
   75 {
   76     switch (service)
   77     {
   78     case password_service_smtp:
   79         return "smtp";
   80     case password_service_pop3:
   81         return "pop3";
   82     }
   83     return NULL;
   84 }
   85 #endif
   86 
   87 char *password_get(const char *hostname, const char *user,
   88         password_service_t service, int getpass_only_via_tty)
   89 {
   90     char *password = NULL;
   91 
   92 #ifdef HAVE_LIBSECRET
   93     if (!password)
   94     {
   95         gchar* libsecret_pw = secret_password_lookup_sync(
   96                 get_schema(),
   97                 NULL, NULL,
   98                 "host", hostname,
   99                 "service", service_string(service),
  100                 "user", user,
  101                 NULL);
  102         if (!libsecret_pw)
  103         {
  104             /* for compatibility with passwords stored by the older
  105              * libgnome-keyring */
  106             libsecret_pw = secret_password_lookup_sync(
  107                     SECRET_SCHEMA_COMPAT_NETWORK,
  108                     NULL, NULL,
  109                     "user", user,
  110                     "protocol", service_string(service),
  111                     "server", hostname,
  112                     NULL);
  113         }
  114         if (libsecret_pw)
  115         {
  116             password = xstrdup(libsecret_pw);
  117             secret_password_free(libsecret_pw);
  118         }
  119     }
  120 #endif /* HAVE_LIBSECRET */
  121 
  122 #ifdef HAVE_MACOSXKEYRING
  123     if (!password)
  124     {
  125         void *password_data;
  126         UInt32 password_length;
  127         if (SecKeychainFindInternetPassword(
  128                     NULL,
  129                     strlen(hostname), hostname,
  130                     0, NULL,
  131                     strlen(user), user,
  132                     0, (char *)NULL,
  133                     0,
  134                     service == password_service_smtp ? kSecProtocolTypeSMTP : kSecProtocolTypePOP3,
  135                     kSecAuthenticationTypeDefault,
  136                     &password_length, &password_data,
  137                     NULL) == noErr)
  138         {
  139             password = xmalloc((password_length + 1) * sizeof(char));
  140             strncpy(password, password_data, (size_t)password_length);
  141             password[password_length] = '\0';
  142             SecKeychainItemFreeContent(NULL, password_data);
  143         }
  144     }
  145 #endif /* HAVE_MACOSXKEYRING */
  146 
  147     if (!password)
  148     {
  149         char *netrc_directory;
  150         char *netrc_filename;
  151         netrc_entry *netrc_hostlist;
  152         netrc_entry *netrc_host;
  153 
  154         netrc_directory = get_homedir();
  155         netrc_filename = get_filename(netrc_directory, USERNETRCFILE);
  156         free(netrc_directory);
  157         if ((netrc_hostlist = parse_netrc(netrc_filename)))
  158         {
  159             if ((netrc_host = search_netrc(netrc_hostlist, hostname, user)))
  160             {
  161                 password = xstrdup(netrc_host->password);
  162             }
  163             free_netrc(netrc_hostlist);
  164         }
  165         free(netrc_filename);
  166         if (!password)
  167         {
  168             netrc_directory = get_sysconfdir();
  169             netrc_filename = get_filename(netrc_directory, SYSNETRCFILE);
  170             free(netrc_directory);
  171             if ((netrc_hostlist = parse_netrc(netrc_filename)))
  172             {
  173                 if ((netrc_host = search_netrc(netrc_hostlist, hostname, user)))
  174                 {
  175                     password = xstrdup(netrc_host->password);
  176                 }
  177                 free_netrc(netrc_hostlist);
  178             }
  179             free(netrc_filename);
  180         }
  181     }
  182 
  183     if (!password)
  184     {
  185         int getpass_is_allowed = 1;
  186         if (getpass_only_via_tty)
  187         {
  188             /* Do not let getpass() read from stdin, because we read the mail from
  189              * there. Our W32 getpass() uses _getch(), which always reads from the
  190              * 'console' and not stdin. On other systems, we test if /dev/tty can be
  191              * opened before calling getpass(). */
  192             int getpass_uses_tty;
  193             FILE *tty;
  194 #if defined W32_NATIVE || defined __CYGWIN__
  195             getpass_uses_tty = 1;
  196 #else
  197             getpass_uses_tty = 0;
  198             if ((tty = fopen("/dev/tty", "w+")))
  199             {
  200                 getpass_uses_tty = 1;
  201                 fclose(tty);
  202             }
  203 #endif
  204             if (!getpass_uses_tty)
  205             {
  206                 getpass_is_allowed = 0;
  207             }
  208         }
  209         if (getpass_is_allowed)
  210         {
  211             char *prompt = xasprintf(_("password for %s at %s: "), user, hostname);
  212             char *gpw = getpass(prompt);
  213             free(prompt);
  214             if (gpw)
  215             {
  216                 password = xstrdup(gpw);
  217             }
  218         }
  219     }
  220 
  221     return password;
  222 }