attribute.c: Remove pointless condition in attribute_open().
[paraslash.git] / crypt_common.c
1 /*
2  * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
8
9 #include <regex.h>
10
11 #include "para.h"
12 #include "error.h"
13 #include "string.h"
14 #include "crypt.h"
15 #include "crypt_backend.h"
16
17 /** If the key begins with this text, we treat it as an ssh key. */
18 #define KEY_TYPE_TXT "ssh-rsa"
19
20 /**
21  * Check if given buffer starts with a ssh rsa key signature.
22  *
23  * \param data The buffer.
24  * \param size Number of data bytes.
25  *
26  * \return Number of header bytes to be skipped on success, zero if
27  * ssh rsa signature was not found.
28  */
29 size_t is_ssh_rsa_key(char *data, size_t size)
30 {
31         char *cp;
32
33         if (size < strlen(KEY_TYPE_TXT) + 2)
34                 return 0;
35         cp = memchr(data, ' ', size);
36         if (cp == NULL)
37                 return 0;
38         if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
39                 return 0;
40         cp++;
41         if (cp >= data + size)
42                 return 0;
43         if (*cp == '\0')
44                 return 0;
45         return cp - data;
46 }
47
48 /*
49  * This base64/uudecode stuff below is taken from openssh-5.2p1, Copyright (c)
50  * 1996 by Internet Software Consortium.  Portions Copyright (c) 1995 by
51  * International Business Machines, Inc.
52  */
53
54 static const char Base64[] =
55         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
56 static const char Pad64 = '=';
57
58 /**
59  * base64-decode a buffer.
60  *
61  * \param src The buffer to decode.
62  * \param target Result is stored here.
63  * \param targsize Number of bytes of \a target.
64  *
65  * Skips all whitespace anywhere. Converts characters, four at a time, starting
66  * at (or after) src from base - 64 numbers into three 8 bit bytes in the
67  * target area.
68  *
69  * \return The number of data bytes stored at the target, -E_BASE64 on errors.
70  */
71 int base64_decode(char const *src, unsigned char *target, size_t targsize)
72 {
73         unsigned int tarindex, state;
74         int ch;
75         char *pos;
76
77         state = 0;
78         tarindex = 0;
79
80         while ((ch = *src++) != '\0') {
81                 if (para_isspace(ch)) /* Skip whitespace anywhere. */
82                         continue;
83
84                 if (ch == Pad64)
85                         break;
86
87                 pos = strchr(Base64, ch);
88                 if (pos == NULL) /* A non-base64 character. */
89                         return -E_BASE64;
90
91                 switch (state) {
92                 case 0:
93                         if (tarindex >= targsize)
94                                 return -E_BASE64;
95                         target[tarindex] = (pos - Base64) << 2;
96                         state = 1;
97                         break;
98                 case 1:
99                         if (tarindex + 1 >= targsize)
100                                 return -E_BASE64;
101                         target[tarindex] |= (pos - Base64) >> 4;
102                         target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
103                         tarindex++;
104                         state = 2;
105                         break;
106                 case 2:
107                         if (tarindex + 1 >= targsize)
108                                 return -E_BASE64;
109                         target[tarindex] |= (pos - Base64) >> 2;
110                         target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
111                         tarindex++;
112                         state = 3;
113                         break;
114                 case 3:
115                         if (tarindex >= targsize)
116                                 return -E_BASE64;
117                         target[tarindex] |= pos - Base64;
118                         tarindex++;
119                         state = 0;
120                         break;
121                 }
122         }
123
124         /*
125          * We are done decoding Base-64 chars.  Let's see if we ended
126          * on a byte boundary, and/or with erroneous trailing characters.
127          */
128
129         if (ch == Pad64) {              /* We got a pad char. */
130                 ch = *src++;            /* Skip it, get next. */
131                 switch (state) {
132                 case 0:         /* Invalid = in first position */
133                 case 1:         /* Invalid = in second position */
134                         return -E_BASE64;
135
136                 case 2:         /* Valid, means one byte of info */
137                         /* Skip any number of spaces. */
138                         for (; ch != '\0'; ch = *src++)
139                                 if (!isspace(ch))
140                                         break;
141                         /* Make sure there is another trailing = sign. */
142                         if (ch != Pad64)
143                                 return -E_BASE64;
144                         ch = *src++;            /* Skip the = */
145                         /* Fall through to "single trailing =" case. */
146                         /* FALLTHROUGH */
147
148                 case 3:         /* Valid, means two bytes of info */
149                         /*
150                          * We know this char is an =.  Is there anything but
151                          * whitespace after it?
152                          */
153                         for (; ch != '\0'; ch = *src++)
154                                 if (!isspace(ch))
155                                         return -E_BASE64;
156
157                         /*
158                          * Now make sure for cases 2 and 3 that the "extra"
159                          * bits that slopped past the last full byte were
160                          * zeros.  If we don't check them, they become a
161                          * subliminal channel.
162                          */
163                         if (target[tarindex] != 0)
164                                 return -E_BASE64;
165                 }
166         } else {
167                 /*
168                  * We ended by seeing the end of the string.  Make sure we
169                  * have no partial bytes lying around.
170                  */
171                 if (state != 0)
172                         return -E_BASE64;
173         }
174
175         return tarindex;
176 }
177
178 /**
179  * uudecode a buffer.
180  *
181  * \param src The buffer to decode.
182  * \param target Result buffer.
183  * \param targsize The length of \a target in bytes.
184  *
185  * This is just a simple wrapper for base64_decode() which strips whitespace.
186  *
187  * \return The return value of the underlying call to base64_decode().
188  */
189 int uudecode(const char *src, unsigned char *target, size_t targsize)
190 {
191         int len;
192         char *encoded, *p;
193
194         /* copy the 'readonly' source */
195         encoded = para_strdup(src);
196         /* skip whitespace and data */
197         for (p = encoded; *p == ' ' || *p == '\t'; p++)
198                 ;
199         for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
200                 ;
201         /* and remove trailing whitespace because base64_decode needs this */
202         *p = '\0';
203         len = base64_decode(encoded, target, targsize);
204         free(encoded);
205         return len;
206 }
207
208 /**
209  * Read a 4-byte number from a buffer in big-endian format.
210  *
211  * \param vp The buffer.
212  *
213  * The byte-order of the buffer is expected to be big-endian, unlike read_u32()
214  * of portable_io.h which expects little endian.
215  *
216  * \return The 32 bit number given by \a vp.
217  */
218 uint32_t read_ssh_u32(const void *vp)
219 {
220         const unsigned char *p = (const unsigned char *)vp;
221         uint32_t v;
222
223         v  = (uint32_t)p[0] << 24;
224         v |= (uint32_t)p[1] << 16;
225         v |= (uint32_t)p[2] << 8;
226         v |= (uint32_t)p[3];
227
228         return v;
229 }
230
231 /**
232  * Sanity checks for the header of an ssh key.
233  *
234  * \param blob The buffer.
235  * \param blen The number of bytes of \a blob.
236  *
237  * This performs some checks to make sure we really have an ssh key. It also
238  * computes the offset in bytes of the start of the key values (modulus,
239  * exponent..).
240  *
241  * \return The number of bytes to skip until the start of the first encoded
242  * number (usually 11).
243  */
244 int check_ssh_key_header(const unsigned char *blob, int blen)
245 {
246         const unsigned char *p = blob, *end = blob + blen;
247         uint32_t rlen;
248
249         if (p + 4 > end)
250                 return -E_SSH_KEY_HEADER;
251         rlen = read_ssh_u32(p);
252         p += 4;
253         if (p + rlen < p)
254                 return -E_SSH_KEY_HEADER;
255         if (p + rlen > end)
256                 return -E_SSH_KEY_HEADER;
257         if (rlen < strlen(KEY_TYPE_TXT))
258                 return -E_SSH_KEY_HEADER;
259         PARA_DEBUG_LOG("type: %s, rlen: %d\n", p, rlen);
260         if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
261                 return -E_SSH_KEY_HEADER;
262         return 4 + rlen;
263 }
264
265 /**
266  * Check existence and permissions of a key file.
267  *
268  * \param file The path of the key file.
269  * \param private_key Whether this is a private key.
270  *
271  * This checks whether the file exists. If it is a private key, we additionally
272  * check that the permissions are restrictive enough. It is considered an error
273  * if we own the file and it is readable for others.
274  *
275  * \return Standard.
276  */
277 int check_key_file(const char *file, bool private_key)
278 {
279         struct stat st;
280
281         if (stat(file, &st) != 0)
282                 return -ERRNO_TO_PARA_ERROR(errno);
283         if (!private_key)
284                 return 0;
285         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
286                 return -E_KEY_PERM;
287         return 1;
288 }
289
290 void hash_to_asc(unsigned char *hash, char *asc)
291 {
292         int i;
293         const char hexchar[] = "0123456789abcdef";
294
295         for (i = 0; i < HASH_SIZE; i++) {
296                 asc[2 * i] = hexchar[hash[i] >> 4];
297                 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
298         }
299         asc[2 * HASH_SIZE] = '\0';
300 }
301
302 int hash_compare(unsigned char *h1, unsigned char *h2)
303 {
304         int i;
305
306         for (i = 0; i < HASH_SIZE; i++) {
307                 if (h1[i] < h2[i])
308                         return -1;
309                 if (h1[i] > h2[i])
310                         return 1;
311         }
312         return 0;
313 }