Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / armor.c
1
2 #if defined(__linux__)
3 #include <linux/errno.h>
4 #else
5 #include <sys/errno.h>
6 #endif
7
8 /*
9  * base64 encode/decode.
10  */
11
12 const char *pem_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13
14 static int encode_bits(int c)
15 {
16         return pem_key[c];
17 }
18
19 static int decode_bits(char c)
20 {
21         if (c >= 'A' && c <= 'Z')
22                 return c - 'A';
23         if (c >= 'a' && c <= 'z')
24                 return c - 'a' + 26;
25         if (c >= '0' && c <= '9')
26                 return c - '0' + 52;
27         if (c == '+' || c == '-')
28                 return 62;
29         if (c == '/' || c == '_')
30                 return 63;
31         if (c == '=')
32                 return 0; /* just non-negative, please */
33         return -EINVAL; 
34 }
35
36 static int set_str_val(char **pdst, const char *end, char c)
37 {
38         if (*pdst < end) {
39                 char *p = *pdst;
40                 *p = c;
41                 (*pdst)++;
42         } else
43                 return -ERANGE;
44
45         return 0;
46 }
47
48 int ceph_armor_line_break(char *dst, const char *dst_end, const char *src, const char *end, int line_width)
49 {
50         int olen = 0;
51         int line = 0;
52
53 #define SET_DST(c) do { \
54         int __ret = set_str_val(&dst, dst_end, c); \
55         if (__ret < 0) \
56                 return __ret; \
57 } while (0);
58
59         while (src < end) {
60                 unsigned char a;
61
62                 a = *src++;
63                 SET_DST(encode_bits(a >> 2));
64                 if (src < end) {
65                         unsigned char b;
66                         b = *src++;
67                         SET_DST(encode_bits(((a & 3) << 4) | (b >> 4)));
68                         if (src < end) {
69                                 unsigned char c;
70                                 c = *src++;
71                                 SET_DST(encode_bits(((b & 15) << 2) |
72                                                                 (c >> 6)));
73                                 SET_DST(encode_bits(c & 63));
74                         } else {
75                                 SET_DST(encode_bits((b & 15) << 2));
76                                 SET_DST('=');
77                         }
78                 } else {
79                         SET_DST(encode_bits(((a & 3) << 4)));
80                         SET_DST('=');
81                         SET_DST('=');
82                 }
83                 olen += 4;
84                 line += 4;
85                 if (line_width && line == line_width) {
86                         line = 0;
87                         SET_DST('\n');
88                         olen++;
89                 }
90         }
91         return olen;
92 }
93
94 int ceph_armor(char *dst, const char *dst_end, const char *src, const char *end)
95 {
96         return ceph_armor_line_break(dst, dst_end, src, end, 0);
97 }
98
99 int ceph_unarmor(char *dst, const char *dst_end, const char *src, const char *end)
100 {
101         int olen = 0;
102
103         while (src < end) {
104                 int a, b, c, d;
105
106                 if (src[0] == '\n') {
107                         src++;
108                         continue;
109                 }
110
111                 if (src + 4 > end)
112                         return -EINVAL;
113                 a = decode_bits(src[0]);
114                 b = decode_bits(src[1]);
115                 c = decode_bits(src[2]);
116                 d = decode_bits(src[3]);
117                 if (a < 0 || b < 0 || c < 0 || d < 0)
118                         return -EINVAL;
119
120                 SET_DST((a << 2) | (b >> 4));
121                 if (src[2] == '=')
122                         return olen + 1;
123                 SET_DST(((b & 15) << 4) | (c >> 2));
124                 if (src[3] == '=')
125                         return olen + 2;
126                 SET_DST(((c & 3) << 6) | d);
127                 olen += 3;
128                 src += 4;
129         }
130         return olen;
131 }