client: Use lsu_merge_config_file_options().
[paraslash.git] / crypt_common.c
1 /* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
4
5 #include <regex.h>
6
7 #include "para.h"
8 #include "error.h"
9 #include "string.h"
10 #include "crypt.h"
11 #include "crypt_backend.h"
12 #include "portable_io.h"
13
14 /** If the key begins with this text, we treat it as an ssh key. */
15 #define KEY_TYPE_TXT "ssh-rsa"
16
17 /**
18  * Check if given buffer starts with a ssh rsa key signature.
19  *
20  * \param data The buffer.
21  * \param size Number of data bytes.
22  *
23  * \return Number of header bytes to be skipped on success, zero if
24  * ssh rsa signature was not found.
25  */
26 size_t is_ssh_rsa_key(char *data, size_t size)
27 {
28         char *cp;
29
30         if (size < strlen(KEY_TYPE_TXT) + 2)
31                 return 0;
32         cp = memchr(data, ' ', size);
33         if (cp == NULL)
34                 return 0;
35         if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
36                 return 0;
37         cp++;
38         if (cp >= data + size)
39                 return 0;
40         if (*cp == '\0')
41                 return 0;
42         return cp - data;
43 }
44
45 /**
46  * Sanity checks for the header of an ssh key.
47  *
48  * \param blob The buffer.
49  * \param blen The number of bytes of \a blob.
50  *
51  * This performs some checks to make sure we really have an ssh key. It also
52  * computes the offset in bytes of the start of the key values (modulus,
53  * exponent..).
54  *
55  * \return The number of bytes to skip until the start of the first encoded
56  * number (usually 11).
57  */
58 int check_ssh_key_header(const unsigned char *blob, int blen)
59 {
60         const unsigned char *p = blob, *end = blob + blen;
61         uint32_t rlen;
62
63         if (p + 4 > end)
64                 return -E_SSH_KEY_HEADER;
65         rlen = read_u32_be(p);
66         p += 4;
67         if (p + rlen < p)
68                 return -E_SSH_KEY_HEADER;
69         if (p + rlen > end)
70                 return -E_SSH_KEY_HEADER;
71         if (rlen < strlen(KEY_TYPE_TXT))
72                 return -E_SSH_KEY_HEADER;
73         PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen);
74         if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
75                 return -E_SSH_KEY_HEADER;
76         return 4 + rlen;
77 }
78
79 /**
80  * Check existence and permissions of a private key file.
81  *
82  * \param file The path of the key file.
83  *
84  * This checks whether the file exists and its permissions are restrictive
85  * enough. It is considered an error if we own the file and it is readable for
86  * others.
87  *
88  * \return Standard.
89  */
90 int check_private_key_file(const char *file)
91 {
92         struct stat st;
93
94         if (stat(file, &st) != 0)
95                 return -ERRNO_TO_PARA_ERROR(errno);
96         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
97                 return -E_KEY_PERM;
98         return 1;
99 }
100
101 void hash_to_asc(unsigned char *hash, char *asc)
102 {
103         int i;
104         const char hexchar[] = "0123456789abcdef";
105
106         for (i = 0; i < HASH_SIZE; i++) {
107                 asc[2 * i] = hexchar[hash[i] >> 4];
108                 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
109         }
110         asc[2 * HASH_SIZE] = '\0';
111 }
112
113 int hash_compare(unsigned char *h1, unsigned char *h2)
114 {
115         int i;
116
117         for (i = 0; i < HASH_SIZE; i++) {
118                 if (h1[i] < h2[i])
119                         return -1;
120                 if (h1[i] > h2[i])
121                         return 1;
122         }
123         return 0;
124 }