Require GnuTLS version >= 3.3.0.
[libpwmd.git] / src / misc.c
blob565537e415283cc814062e8d519f518f27aeeb2f
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
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;
52 struct passwd t;
54 if (!p)
55 return NULL;
57 if (*p != '~' || *(p + 1) != '/')
58 return pwmd_strdup (p);
60 if (!pw)
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);
71 pwmd_free (pwbuf);
72 return result;
75 char *
76 _getpwuid (struct passwd *pwd)
78 size_t size = sysconf (_SC_GETPW_R_SIZE_MAX);
79 struct passwd *result;
80 char *buf;
81 int n;
83 if (size == -1)
84 size = 16384;
86 buf = pwmd_malloc (size);
87 if (!buf)
88 return NULL;
90 n = getpwuid_r (getuid (), pwd, buf, size, &result);
91 if (n)
93 pwmd_free (buf);
94 errno = n;
95 return NULL;
98 if (!result)
100 pwmd_free (buf);
101 return NULL;
104 errno = n;
105 return buf;
107 #else
108 char *
109 _expand_homedir (char *str, struct passwd *pw)
111 char *p = str;
113 if (!p)
114 return NULL;
116 if (*p != '~' || *(p + 1) != '/')
117 return pwmd_strdup (p);
119 if (!pw)
121 pw = getpwuid (getuid ());
122 if (!pw)
123 return NULL;
126 p += 2;
127 return pwmd_strdup_printf ("%s/%s", pw->pw_dir, p);
130 char *
131 _getpwuid (struct passwd *pwd)
133 struct passwd *pw = getpwuid (getuid ());
135 if (!pw)
136 return NULL;
138 *pwd = *pw;
139 return pwmd_strdup ("");
141 #endif
144 * Borrowed from libassuan.
146 char *
147 _percent_escape (const char *atext)
149 const unsigned char *s;
150 int len;
151 char *buf, *p;
153 if (!atext)
154 return NULL;
156 len = strlen (atext) * 3 + 1;
157 buf = (char *) pwmd_malloc (len);
159 if (!buf)
160 return NULL;
162 p = buf;
164 for (s = (const unsigned char *) atext; *s; s++)
166 if (*s < ' ')
168 sprintf (p, "%%%02X", *s);
169 p += 3;
171 else
172 *p++ = *s;
175 *p = 0;
176 return buf;
179 void
180 update_pinentry_settings (pwm_t * pwm)
182 FILE *fp;
183 char buf[LINE_MAX];
184 char *p;
185 struct passwd pw;
186 char *pwbuf = _getpwuid (&pw);
188 if (!pwbuf)
189 return;
191 snprintf (buf, sizeof (buf), "%s/.pwmd/pinentry.conf", pw.pw_dir);
193 if ((fp = fopen (buf, "r")) == NULL)
195 pwmd_free (pwbuf);
196 return;
199 while ((p = fgets (buf, sizeof (buf), fp)) != NULL)
201 char name[32] = {0}, val[256] = {0};
203 if (sscanf (p, " %31[a-zA-Z] = %255s", name, val) != 2)
204 continue;
206 if (strcasecmp (name, "TTYNAME") == 0)
208 pwmd_free (pwm->pinentry_tty);
209 pwm->pinentry_tty = pwmd_strdup (val);
210 if (!pwm->pinentry_tty)
211 goto fail;
213 else if (strcasecmp (name, "TTYTYPE") == 0)
215 pwmd_free (pwm->pinentry_term);
216 pwm->pinentry_term = pwmd_strdup (val);
217 if (!pwm->pinentry_term)
218 goto fail;
220 else if (strcasecmp (name, "DISPLAY") == 0)
222 pwmd_free (pwm->pinentry_display);
223 pwm->pinentry_display = pwmd_strdup (val);
224 if (!pwm->pinentry_display)
225 goto fail;
227 else if (strcasecmp (name, "PATH") == 0)
229 pwmd_free (pwm->pinentry_path);
230 pwm->pinentry_path = _expand_homedir (val, &pw);
231 if (!pwm->pinentry_path)
232 goto fail;
234 else if (strcasecmp (name, "LC_MESSAGES") == 0)
236 pwmd_free (pwm->pinentry_lcmessages);
237 pwm->pinentry_lcmessages = pwmd_strdup (val);
238 if (!pwm->pinentry_lcmessages)
239 goto fail;
241 else if (strcasecmp (name, "LC_CTYPE") == 0)
243 pwmd_free (pwm->pinentry_lcctype);
244 pwm->pinentry_lcctype = pwmd_strdup (val);
245 if (!pwm->pinentry_lcctype)
246 goto fail;
250 fail:
251 pwmd_free (pwbuf);
252 fclose (fp);
255 /* Common hostname parsing for urls. Handles both IPv4 and IPv6 hostname and
256 * port specification.
258 gpg_error_t
259 parse_hostname_common (const char *str, char **host, int *port)
261 const char *p = str;
262 char *t = NULL;
264 /* IPv6 with optional port. */
265 if (*p == '[')
267 p++;
268 t = strchr (p, ']');
270 else
272 int n = 0;
273 const char *x;
275 /* Handle IPv6 without proper braces around the IP. */
276 for (x = p; *x; x++)
278 if (*x == ':')
279 n++;
282 if (n <= 1)
283 t = strchr (p, ':');
286 if (t)
288 size_t len = strlen (p) - strlen (t) + 1;
290 *host = pwmd_malloc (len);
291 if (!*host)
292 return gpg_error_from_errno (ENOMEM);
294 snprintf (*host, len, "%s", p);
295 t++;
297 if (*t == ':')
298 t++;
300 if (*t)
301 *port = strtol (t, NULL, 10);
303 if (*t == '-')
304 t++;
306 while (*t && isdigit (*t))
307 t++;
309 p = t;
311 else
313 *host = pwmd_strdup (str);
314 if (!*host)
315 return gpg_error_from_errno (ENOMEM);
318 return 0;
321 char *
322 bin2hex (const unsigned char *data, size_t len)
324 size_t size = len * 2 + 1;
325 char buf[size]; // C99
326 size_t n;
328 buf[0] = 0;
330 for (n = 0; n < len; n++)
332 char c[3];
334 sprintf (c, "%02X", data[n]);
335 strcat (buf, c);
338 return pwmd_strdup (buf);