No longer set PWMD_OPTION_NO_PINENTRY for remote connections.
[libpwmd.git] / src / misc.c
blob15375e00220b01b120e744cc8ea18a1535cb9979
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of libpwmd.
8 Libpwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Libpwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #ifdef HAVE_LIMITS_H
26 #include <limits.h>
27 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <ctype.h>
39 #ifndef LINE_MAX
40 #define LINE_MAX 2048
41 #endif
43 #include <libpwmd.h>
44 #include "misc.h"
46 #ifdef HAVE_GETPWUID_R
47 char *_expand_homedir(char *str, struct passwd *pw)
49 char *p = str;
50 char *pwbuf = NULL;
51 char *result;
53 if (!p)
54 return NULL;
56 if (*p != '~' || *(p+1) != '/')
57 return pwmd_strdup(p);
59 if (!pw) {
60 struct passwd t;
62 pwbuf = _getpwuid(&t);
63 if (!pwbuf)
64 return NULL;
66 pw = &t;
69 p += 2;
70 result = pwmd_strdup_printf("%s/%s", pw->pw_dir, p);
72 if (pwbuf)
73 pwmd_free(pwbuf);
75 return result;
78 char *_getpwuid(struct passwd *pwd)
80 size_t size = sysconf(_SC_GETPW_R_SIZE_MAX);
81 struct passwd *result;
82 char *buf;
83 int n;
85 if (size == -1)
86 size = 16384;
88 buf = pwmd_malloc(size);
89 if (!buf)
90 return NULL;
92 n = getpwuid_r(getuid(), pwd, buf, size, &result);
93 if (n) {
94 pwmd_free(buf);
95 errno = n;
96 return NULL;
99 if (!result) {
100 pwmd_free(buf);
101 return NULL;
104 errno = n;
105 return buf;
107 #else
108 char *_expand_homedir(char *str, struct passwd *pw)
110 char *p = str;
112 if (!p)
113 return NULL;
115 if (*p != '~' || *(p+1) != '/')
116 return pwmd_strdup(p);
118 if (!pw) {
119 pw = getpwuid(getuid());
120 if (!pw)
121 return NULL;
124 p += 2;
125 return pwmd_strdup_printf("%s/%s", pw->pw_dir, p);
128 char *_getpwuid(struct passwd *pwd)
130 struct passwd *pw = getpwuid(getuid());
132 if (!pw)
133 return NULL;
135 *pwd = *pw;
136 return pwmd_strdup("");
138 #endif
141 * Borrowed from libassuan.
143 char *_percent_escape(const char *atext)
145 const unsigned char *s;
146 int len;
147 char *buf, *p;
149 if (!atext)
150 return NULL;
152 len = strlen(atext) * 3 + 1;
153 buf = (char *)pwmd_malloc(len);
155 if (!buf)
156 return NULL;
158 p = buf;
160 for (s=(const unsigned char *)atext; *s; s++) {
161 if (*s < ' ') {
162 sprintf (p, "%%%02X", *s);
163 p += 3;
165 else
166 *p++ = *s;
169 *p = 0;
170 return buf;
173 void update_pinentry_settings(pwm_t *pwm)
175 FILE *fp;
176 char buf[LINE_MAX];
177 char *p;
178 struct passwd pw;
179 char *pwbuf = _getpwuid(&pw);
181 if (!pwbuf)
182 return;
184 snprintf(buf, sizeof(buf), "%s/.pwmd/pinentry.conf", pw.pw_dir);
186 if ((fp = fopen(buf, "r")) == NULL) {
187 pwmd_free(pwbuf);
188 return;
191 while ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
192 char name[32], val[256];
194 if (sscanf(p, " %32[a-zA-Z] = %256s", name, val) != 2)
195 continue;
197 if (strcasecmp(name, "TTYNAME") == 0) {
198 pwmd_free(pwm->pinentry_tty);
199 pwm->pinentry_tty = pwmd_strdup(val);
200 if (!pwm->pinentry_tty)
201 goto fail;
203 else if (strcasecmp(name, "TTYTYPE") == 0) {
204 pwmd_free(pwm->pinentry_term);
205 pwm->pinentry_term = pwmd_strdup(val);
206 if (!pwm->pinentry_term)
207 goto fail;
209 else if (strcasecmp(name, "DISPLAY") == 0) {
210 pwmd_free(pwm->pinentry_display);
211 pwm->pinentry_display = pwmd_strdup(val);
212 if (!pwm->pinentry_display)
213 goto fail;
215 else if (strcasecmp(name, "PATH") == 0) {
216 pwmd_free(pwm->pinentry_path);
217 pwm->pinentry_path = _expand_homedir(val, &pw);
218 if (!pwm->pinentry_path)
219 goto fail;
221 else if (strcasecmp(name, "LC_MESSAGES") == 0) {
222 pwmd_free(pwm->pinentry_lcmessages);
223 pwm->pinentry_lcmessages = pwmd_strdup(val);
224 if (!pwm->pinentry_lcmessages)
225 goto fail;
227 else if (strcasecmp(name, "LC_CTYPE") == 0) {
228 pwmd_free(pwm->pinentry_lcctype);
229 pwm->pinentry_lcctype = pwmd_strdup(val);
230 if (!pwm->pinentry_lcctype)
231 goto fail;
235 fail:
236 pwmd_free(pwbuf);
237 fclose(fp);
240 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
241 * port specification.
243 gpg_error_t parse_hostname_common(const char *str, char **host, int *port)
245 const char *p = str;
246 char *t = NULL;
247 size_t len;
249 /* IPv6 with optional port. */
250 if (*p == '[') {
251 p++;
252 t = strchr(p, ']');
254 else {
255 int n = 0;
256 const char *x;
258 /* Handle IPv6 without proper braces around the IP. */
259 for (x = p; *x; x++) {
260 if (*x == ':')
261 n++;
264 if (n <= 1)
265 t = strchr(p, ':');
268 if (t) {
269 len = strlen(p)-strlen(t)+1;
270 *host = pwmd_malloc(len);
271 if (!*host)
272 return gpg_error_from_errno(ENOMEM);
274 snprintf(*host, len, "%s", p);
275 t++;
277 if (*t == ':')
278 t++;
280 if (*t)
281 *port = strtol(t, NULL, 10);
283 if (*t == '-')
284 t++;
286 while (*t && isdigit(*t))
287 t++;
289 p = t;
291 else {
292 *host = pwmd_strdup(str);
293 if (!*host)
294 return gpg_error_from_errno(ENOMEM);
297 return 0;