pwmc: add the '.passwd' command.
[libpwmd.git] / src / misc.c
blob25dc7175b982db48c6d43d6d30a1028b463c7c7f
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of libpwmd.
7 Libpwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Libpwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #ifdef HAVE_LIMITS_H
25 #include <limits.h>
26 #endif
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ctype.h>
38 #ifndef LINE_MAX
39 #define LINE_MAX 2048
40 #endif
42 #include <libpwmd.h>
43 #include "misc.h"
45 #ifdef HAVE_GETPWUID_R
46 char *
47 _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)
61 struct passwd t;
63 pwbuf = _getpwuid (&t);
64 if (!pwbuf)
65 return NULL;
67 pw = &t;
70 p += 2;
71 result = pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
72 pwmd_free (pwbuf);
73 return result;
76 char *
77 _getpwuid (struct passwd *pwd)
79 size_t size = sysconf (_SC_GETPW_R_SIZE_MAX);
80 struct passwd *result;
81 char *buf;
82 int n;
84 if (size == -1)
85 size = 16384;
87 buf = pwmd_malloc (size);
88 if (!buf)
89 return NULL;
91 n = getpwuid_r (getuid (), pwd, buf, size, &result);
92 if (n)
94 pwmd_free (buf);
95 errno = n;
96 return NULL;
99 if (!result)
101 pwmd_free (buf);
102 return NULL;
105 errno = n;
106 return buf;
108 #else
109 char *
110 _expand_homedir (char *str, struct passwd *pw)
112 char *p = str;
114 if (!p)
115 return NULL;
117 if (*p != '~' || *(p + 1) != '/')
118 return pwmd_strdup (p);
120 if (!pw)
122 pw = getpwuid (getuid ());
123 if (!pw)
124 return NULL;
127 p += 2;
128 return pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
131 char *
132 _getpwuid (struct passwd *pwd)
134 struct passwd *pw = getpwuid (getuid ());
136 if (!pw)
137 return NULL;
139 *pwd = *pw;
140 return pwmd_strdup ("");
142 #endif
145 * Borrowed from libassuan.
147 char *
148 _percent_escape (const char *atext)
150 const unsigned char *s;
151 int len;
152 char *buf, *p;
154 if (!atext)
155 return NULL;
157 len = strlen (atext) * 3 + 1;
158 buf = (char *) pwmd_malloc (len);
160 if (!buf)
161 return NULL;
163 p = buf;
165 for (s = (const unsigned char *) atext; *s; s++)
167 if (*s < ' ')
169 sprintf (p, "%%%02X", *s);
170 p += 3;
172 else
173 *p++ = *s;
176 *p = 0;
177 return buf;
180 void
181 update_pinentry_settings (pwm_t * pwm)
183 FILE *fp;
184 char buf[LINE_MAX];
185 char *p;
186 struct passwd pw;
187 char *pwbuf = _getpwuid (&pw);
189 if (!pwbuf)
190 return;
192 snprintf (buf, sizeof (buf), "%s/.pwmd/pinentry.conf", pw.pw_dir);
194 if ((fp = fopen (buf, "r")) == NULL)
196 pwmd_free (pwbuf);
197 return;
200 while ((p = fgets (buf, sizeof (buf), fp)) != NULL)
202 char name[32], val[256];
204 if (sscanf (p, " %32[a-zA-Z] = %256s", name, val) != 2)
205 continue;
207 if (strcasecmp (name, "TTYNAME") == 0)
209 pwmd_free (pwm->pinentry_tty);
210 pwm->pinentry_tty = pwmd_strdup (val);
211 if (!pwm->pinentry_tty)
212 goto fail;
214 else if (strcasecmp (name, "TTYTYPE") == 0)
216 pwmd_free (pwm->pinentry_term);
217 pwm->pinentry_term = pwmd_strdup (val);
218 if (!pwm->pinentry_term)
219 goto fail;
221 else if (strcasecmp (name, "DISPLAY") == 0)
223 pwmd_free (pwm->pinentry_display);
224 pwm->pinentry_display = pwmd_strdup (val);
225 if (!pwm->pinentry_display)
226 goto fail;
228 else if (strcasecmp (name, "PATH") == 0)
230 pwmd_free (pwm->pinentry_path);
231 pwm->pinentry_path = _expand_homedir (val, &pw);
232 if (!pwm->pinentry_path)
233 goto fail;
235 else if (strcasecmp (name, "LC_MESSAGES") == 0)
237 pwmd_free (pwm->pinentry_lcmessages);
238 pwm->pinentry_lcmessages = pwmd_strdup (val);
239 if (!pwm->pinentry_lcmessages)
240 goto fail;
242 else if (strcasecmp (name, "LC_CTYPE") == 0)
244 pwmd_free (pwm->pinentry_lcctype);
245 pwm->pinentry_lcctype = pwmd_strdup (val);
246 if (!pwm->pinentry_lcctype)
247 goto fail;
251 fail:
252 pwmd_free (pwbuf);
253 fclose (fp);
256 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
257 * port specification.
259 gpg_error_t
260 parse_hostname_common (const char *str, char **host, int *port)
262 const char *p = str;
263 char *t = NULL;
264 size_t len;
266 /* IPv6 with optional port. */
267 if (*p == '[')
269 p++;
270 t = strchr (p, ']');
272 else
274 int n = 0;
275 const char *x;
277 /* Handle IPv6 without proper braces around the IP. */
278 for (x = p; *x; x++)
280 if (*x == ':')
281 n++;
284 if (n <= 1)
285 t = strchr (p, ':');
288 if (t)
290 len = strlen (p) - strlen (t) + 1;
291 *host = pwmd_malloc (len);
292 if (!*host)
293 return gpg_error_from_errno (ENOMEM);
295 snprintf (*host, len, "%s", p);
296 t++;
298 if (*t == ':')
299 t++;
301 if (*t)
302 *port = strtol (t, NULL, 10);
304 if (*t == '-')
305 t++;
307 while (*t && isdigit (*t))
308 t++;
310 p = t;
312 else
314 *host = pwmd_strdup (str);
315 if (!*host)
316 return gpg_error_from_errno (ENOMEM);
319 return 0;
322 char *
323 bin2hex (const unsigned char *data, size_t len)
325 size_t size = len * 2 + 1;
326 char buf[size]; // C99
327 size_t n;
329 buf[0] = 0;
331 for (n = 0; n < len; n++)
333 char c[3];
335 sprintf (c, "%02X", data[n]);
336 strcat (buf, c);
339 return pwmd_strdup (buf);