]> diplodocus.org Git - nmh/blob - sbr/credentials.c
sendsbr.c: Move interface to own file.
[nmh] / sbr / credentials.c
1 /* credentials.c -- wrap configurable access to .netrc or similar files.
2 *
3 * This code is Copyright (c) 2013, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "concat.h"
10 #include "ruserpass.h"
11 #include "credentials.h"
12 #include "context_find.h"
13 #include "error.h"
14 #include "h/utils.h"
15 #include "h/mts.h"
16 #include "m_maildir.h"
17
18 struct nmh_creds {
19 char *host; /* Hostname corresponding to credentials */
20 char *user; /* Username corresponding to credentials */
21 char *pass; /* (Optional) password used by credentials */
22 };
23
24 void
25 init_credentials_file(void)
26 {
27 if (credentials_file == NULL) {
28 char *cred_style = context_find ("credentials");
29
30 if (cred_style == NULL || ! strcmp (cred_style, "legacy")) {
31 char *hdir = getenv ("HOME");
32
33 credentials_file = concat (hdir ? hdir : ".", "/.netrc", NULL);
34 } else if (! strncasecmp (cred_style, "file:", 5) ||
35 ! strncasecmp (cred_style, "file-nopermcheck:", 17)) {
36 struct stat st;
37 char *filename = strchr(cred_style, ':') + 1;
38
39 while (isspace((unsigned char)*filename))
40 filename++;
41
42 if (*filename == '/') {
43 credentials_file = filename;
44 } else {
45 credentials_file = m_maildir (filename);
46 if (stat (credentials_file, &st) != OK) {
47 credentials_file =
48 concat (mypath ? mypath : ".", "/", filename, NULL);
49 if (stat (credentials_file, &st) != OK) {
50 inform("unable to find credentials file %s, continuing...",
51 filename);
52 }
53 }
54 }
55
56 if (! strncasecmp (cred_style, "file-nopermcheck:", 17))
57 credentials_no_perm_check = 1;
58 }
59 }
60 }
61
62 nmh_creds_t
63 nmh_get_credentials (const char *host, const char *user)
64 {
65 nmh_creds_t creds;
66
67 char *cred_style = context_find ("credentials");
68
69 init_credentials_file ();
70
71 creds = mh_xmalloc(sizeof(*creds));
72
73 creds->host = mh_xstrdup(host);
74 creds->user = NULL;
75 creds->pass = NULL;
76
77 if (cred_style == NULL || ! strcmp (cred_style, "legacy")) {
78 creds->user = user == NULL ? mh_xstrdup(getusername ()) : mh_xstrdup(user);
79 } else if (! strncasecmp (cred_style, "file:", 5) ||
80 ! strncasecmp (cred_style, "file-nopermcheck:", 17)) {
81 /*
82 * Determine user using the first of:
83 * 1) -user switch
84 * 2) matching host entry with login in a credentials file
85 * such as ~/.netrc
86 * 3) interactively request from user (as long as the
87 * credentials file didn't have a "default" token)
88 */
89 creds->user = user == NULL ? NULL : mh_xstrdup(user);
90 } else {
91 inform("unknown credentials style %s, continuing...", cred_style);
92 return NULL;
93 }
94
95 ruserpass(creds->host, &creds->user, &creds->pass,
96 RUSERPASS_NO_PROMPT_USER | RUSERPASS_NO_PROMPT_PASSWORD);
97
98 return creds;
99 }
100
101 /*
102 * Retrieve the username
103 */
104
105 const char *
106 nmh_cred_get_user(nmh_creds_t creds)
107 {
108 if (! creds->user) {
109 ruserpass(creds->host, &creds->user, &creds->pass,
110 RUSERPASS_NO_PROMPT_PASSWORD);
111 }
112
113 return creds->user;
114 }
115
116 /*
117 * Retrieve the password
118 */
119
120 const char *
121 nmh_cred_get_password(nmh_creds_t creds)
122 {
123 if (! creds->pass) {
124 ruserpass(creds->host, &creds->user, &creds->pass, 0);
125 }
126
127 return creds->pass;
128 }
129
130 /*
131 * Free our credentials
132 */
133
134 void
135 nmh_credentials_free(nmh_creds_t creds)
136 {
137 free(creds->host);
138 free(creds->user);
139
140 if (creds->pass) {
141 memset(creds->pass, 0, strlen(creds->pass));
142 free(creds->pass);
143 }
144
145 free(creds);
146 }