]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/iscsid/keys.c
MFC r325067:
[FreeBSD/stable/10.git] / usr.sbin / iscsid / keys.c
1 /*-
2  * Copyright (c) 2012 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Edward Tomasz Napierala under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <assert.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "iscsid.h"
41
42 struct keys *
43 keys_new(void)
44 {
45         struct keys *keys;
46
47         keys = calloc(sizeof(*keys), 1);
48         if (keys == NULL)
49                 log_err(1, "calloc");
50
51         return (keys);
52 }
53
54 void
55 keys_delete(struct keys *keys)
56 {
57
58         free(keys->keys_data);
59         free(keys);
60 }
61
62 void
63 keys_load(struct keys *keys, const struct pdu *pdu)
64 {
65         int i;
66         char *pair;
67         size_t pair_len;
68
69         if (pdu->pdu_data_len == 0)
70                 return;
71
72         if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
73                 log_errx(1, "protocol error: key not NULL-terminated\n");
74
75         assert(keys->keys_data == NULL);
76         keys->keys_data_len = pdu->pdu_data_len;
77         keys->keys_data = malloc(keys->keys_data_len);
78         if (keys->keys_data == NULL)
79                 log_err(1, "malloc");
80         memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len);
81
82         /*
83          * XXX: Review this carefully.
84          */
85         pair = keys->keys_data;
86         for (i = 0;; i++) {
87                 if (i >= KEYS_MAX)
88                         log_errx(1, "too many keys received");
89
90                 pair_len = strlen(pair);
91
92                 keys->keys_values[i] = pair;
93                 keys->keys_names[i] = strsep(&keys->keys_values[i], "=");
94                 if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL)
95                         log_errx(1, "malformed keys");
96                 log_debugx("key received: \"%s=%s\"",
97                     keys->keys_names[i], keys->keys_values[i]);
98
99                 pair += pair_len + 1; /* +1 to skip the terminating '\0'. */
100                 if (pair == keys->keys_data + keys->keys_data_len)
101                         break;
102                 assert(pair < keys->keys_data + keys->keys_data_len);
103         }
104 }
105
106 void
107 keys_save(struct keys *keys, struct pdu *pdu)
108 {
109         char *data;
110         size_t len;
111         int i;
112
113         /*
114          * XXX: Not particularly efficient.
115          */
116         len = 0;
117         for (i = 0; i < KEYS_MAX; i++) {
118                 if (keys->keys_names[i] == NULL)
119                         break;
120                 /*
121                  * +1 for '=', +1 for '\0'.
122                  */
123                 len += strlen(keys->keys_names[i]) +
124                     strlen(keys->keys_values[i]) + 2;
125         }
126
127         if (len == 0)
128                 return;
129
130         data = malloc(len);
131         if (data == NULL)
132                 log_err(1, "malloc");
133
134         pdu->pdu_data = data;
135         pdu->pdu_data_len = len;
136
137         for (i = 0; i < KEYS_MAX; i++) {
138                 if (keys->keys_names[i] == NULL)
139                         break;
140                 data += sprintf(data, "%s=%s",
141                     keys->keys_names[i], keys->keys_values[i]);
142                 data += 1; /* for '\0'. */
143         }
144 }
145
146 const char *
147 keys_find(struct keys *keys, const char *name)
148 {
149         int i;
150
151         /*
152          * Note that we don't handle duplicated key names here,
153          * as they are not supposed to happen in requests, and if they do,
154          * it's an initiator error.
155          */
156         for (i = 0; i < KEYS_MAX; i++) {
157                 if (keys->keys_names[i] == NULL)
158                         return (NULL);
159                 if (strcmp(keys->keys_names[i], name) == 0)
160                         return (keys->keys_values[i]);
161         }
162         return (NULL);
163 }
164
165 void
166 keys_add(struct keys *keys, const char *name, const char *value)
167 {
168         int i;
169
170         log_debugx("key to send: \"%s=%s\"", name, value);
171
172         /*
173          * Note that we don't check for duplicates here, as they are perfectly
174          * fine in responses, e.g. the "TargetName" keys in discovery sesion
175          * response.
176          */
177         for (i = 0; i < KEYS_MAX; i++) {
178                 if (keys->keys_names[i] == NULL) {
179                         keys->keys_names[i] = checked_strdup(name);
180                         keys->keys_values[i] = checked_strdup(value);
181                         return;
182                 }
183         }
184         log_errx(1, "too many keys");
185 }
186
187 void
188 keys_add_int(struct keys *keys, const char *name, int value)
189 {
190         char *str;
191         int ret;
192
193         ret = asprintf(&str, "%d", value);
194         if (ret <= 0)
195                 log_err(1, "asprintf");
196
197         keys_add(keys, name, str);
198         free(str);
199 }