config.c revision 1.2 1 1.2 tron /* $NetBSD: config.c,v 1.2 2006/07/26 11:00:07 tron Exp $ */
2 1.1 gdamore
3 1.1 gdamore /*-
4 1.1 gdamore * Copyright (c) 2006 Itronix Inc.
5 1.1 gdamore * All rights reserved.
6 1.1 gdamore *
7 1.1 gdamore * Redistribution and use in source and binary forms, with or without
8 1.1 gdamore * modification, are permitted provided that the following conditions
9 1.1 gdamore * are met:
10 1.1 gdamore * 1. Redistributions of source code must retain the above copyright
11 1.1 gdamore * notice, this list of conditions and the following disclaimer.
12 1.1 gdamore * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 gdamore * notice, this list of conditions and the following disclaimer in the
14 1.1 gdamore * documentation and/or other materials provided with the distribution.
15 1.1 gdamore * 3. The name of Itronix Inc. may not be used to endorse
16 1.1 gdamore * or promote products derived from this software without specific
17 1.1 gdamore * prior written permission.
18 1.1 gdamore *
19 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
20 1.1 gdamore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 gdamore * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 gdamore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
23 1.1 gdamore * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 1.1 gdamore * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 1.1 gdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 1.1 gdamore * ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 gdamore * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 gdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 gdamore * POSSIBILITY OF SUCH DAMAGE.
30 1.1 gdamore */
31 1.1 gdamore
32 1.1 gdamore #include <sys/cdefs.h>
33 1.2 tron __RCSID("$NetBSD: config.c,v 1.2 2006/07/26 11:00:07 tron Exp $");
34 1.1 gdamore
35 1.1 gdamore #include <sys/time.h>
36 1.2 tron #include <prop/proplib.h>
37 1.1 gdamore #include <bluetooth.h>
38 1.1 gdamore #include <errno.h>
39 1.1 gdamore #include <event.h>
40 1.1 gdamore #include <fcntl.h>
41 1.2 tron #include <stdlib.h>
42 1.1 gdamore #include <string.h>
43 1.1 gdamore #include <syslog.h>
44 1.1 gdamore #include <unistd.h>
45 1.1 gdamore
46 1.1 gdamore #include "bthcid.h"
47 1.1 gdamore
48 1.2 tron static const char *key_file = "/var/db/bthcid.keys";
49 1.2 tron static const char *new_key_file = "/var/db/bthcid.keys.new";
50 1.1 gdamore
51 1.2 tron static prop_dictionary_t
52 1.2 tron load_keys(void)
53 1.1 gdamore {
54 1.2 tron prop_dictionary_t dict;
55 1.2 tron char *xml;
56 1.2 tron off_t len;
57 1.2 tron int fd;
58 1.1 gdamore
59 1.2 tron fd = open(key_file, O_RDONLY, 0);
60 1.2 tron if (fd < 0)
61 1.2 tron return NULL;
62 1.2 tron
63 1.2 tron len = lseek(fd, 0, SEEK_END);
64 1.2 tron if (len == 0) {
65 1.2 tron close(fd);
66 1.2 tron return NULL;
67 1.1 gdamore }
68 1.1 gdamore
69 1.2 tron xml = malloc(len);
70 1.2 tron if (xml == NULL) {
71 1.2 tron close(fd);
72 1.1 gdamore return NULL;
73 1.2 tron }
74 1.1 gdamore
75 1.2 tron (void)lseek(fd, 0, SEEK_SET);
76 1.2 tron if (read(fd, xml, len) != len) {
77 1.2 tron free(xml);
78 1.2 tron close(fd);
79 1.2 tron return NULL;
80 1.1 gdamore }
81 1.1 gdamore
82 1.2 tron dict = prop_dictionary_internalize(xml);
83 1.2 tron free(xml);
84 1.2 tron close(fd);
85 1.2 tron return dict;
86 1.1 gdamore }
87 1.1 gdamore
88 1.2 tron /*
89 1.2 tron * Look up key in keys file. We store a dictionary for each
90 1.2 tron * remote address, and inside that we have a data object for
91 1.2 tron * each local address containing the key.
92 1.2 tron */
93 1.1 gdamore uint8_t *
94 1.2 tron lookup_key(bdaddr_t *laddr, bdaddr_t *raddr)
95 1.1 gdamore {
96 1.2 tron static uint8_t key[HCI_KEY_SIZE];
97 1.2 tron prop_dictionary_t cfg;
98 1.2 tron prop_object_t obj;
99 1.1 gdamore
100 1.2 tron cfg = load_keys();
101 1.2 tron if (cfg == NULL)
102 1.2 tron return NULL;
103 1.2 tron
104 1.2 tron obj = prop_dictionary_get(cfg, bt_ntoa(laddr, NULL));
105 1.2 tron if (obj == NULL || prop_object_type(obj) != PROP_TYPE_DICTIONARY) {
106 1.2 tron prop_object_release(cfg);
107 1.2 tron return NULL;
108 1.1 gdamore }
109 1.1 gdamore
110 1.2 tron obj = prop_dictionary_get(obj, bt_ntoa(raddr, NULL));
111 1.2 tron if (obj == NULL || prop_object_type(obj) != PROP_TYPE_DATA
112 1.2 tron || prop_data_size(obj) != sizeof(key)) {
113 1.2 tron prop_object_release(cfg);
114 1.2 tron return NULL;
115 1.1 gdamore }
116 1.1 gdamore
117 1.2 tron memcpy(key, prop_data_data_nocopy(obj), sizeof(key));
118 1.2 tron prop_object_release(cfg);
119 1.2 tron return key;
120 1.1 gdamore }
121 1.1 gdamore
122 1.1 gdamore void
123 1.1 gdamore save_key(bdaddr_t *laddr, bdaddr_t *raddr, uint8_t *key)
124 1.1 gdamore {
125 1.2 tron prop_dictionary_t cfg, dev;
126 1.2 tron prop_data_t dat;
127 1.2 tron char *xml;
128 1.2 tron int fd;
129 1.2 tron size_t len;
130 1.1 gdamore
131 1.2 tron cfg = load_keys();
132 1.2 tron if (cfg == NULL) {
133 1.2 tron cfg = prop_dictionary_create();
134 1.2 tron if (cfg == NULL) {
135 1.2 tron syslog(LOG_ERR, "prop_dictionary_create() failed. %s (%d)",
136 1.2 tron strerror(errno), errno);
137 1.2 tron
138 1.2 tron return;
139 1.2 tron }
140 1.2 tron }
141 1.2 tron
142 1.2 tron dev = prop_dictionary_get(cfg, bt_ntoa(laddr, NULL));
143 1.2 tron if (dev == NULL) {
144 1.2 tron dev = prop_dictionary_create();
145 1.2 tron if (dev == NULL) {
146 1.2 tron syslog(LOG_ERR, "prop_dictionary_create() failed. %s (%d)",
147 1.2 tron strerror(errno), errno);
148 1.2 tron
149 1.2 tron prop_object_release(cfg);
150 1.2 tron return;
151 1.2 tron }
152 1.2 tron
153 1.2 tron if (!prop_dictionary_set(cfg, bt_ntoa(laddr, NULL), dev)) {
154 1.2 tron syslog(LOG_ERR, "prop_dictionary_set() failed. %s (%d)",
155 1.2 tron strerror(errno), errno);
156 1.2 tron
157 1.2 tron prop_object_release(dev);
158 1.2 tron prop_object_release(cfg);
159 1.2 tron return;
160 1.2 tron }
161 1.2 tron }
162 1.2 tron
163 1.2 tron dat = prop_data_create_data_nocopy(key, HCI_KEY_SIZE);
164 1.2 tron if (dat == NULL) {
165 1.2 tron syslog(LOG_ERR, "Cannot create data object. %s (%d)",
166 1.2 tron strerror(errno), errno);
167 1.2 tron
168 1.2 tron prop_object_release(cfg);
169 1.2 tron return;
170 1.2 tron }
171 1.2 tron
172 1.2 tron if (!prop_dictionary_set(dev, bt_ntoa(raddr, NULL), dat)) {
173 1.2 tron syslog(LOG_ERR, "prop_dictionary_set() failed. %s (%d)",
174 1.2 tron strerror(errno), errno);
175 1.2 tron
176 1.2 tron prop_object_release(dat);
177 1.2 tron prop_object_release(cfg);
178 1.2 tron return;
179 1.2 tron }
180 1.2 tron
181 1.2 tron xml = prop_dictionary_externalize(cfg);
182 1.2 tron if (xml == NULL) {
183 1.2 tron syslog(LOG_ERR, "prop_dictionary_externalize() failed. %s (%d)",
184 1.2 tron strerror(errno), errno);
185 1.2 tron
186 1.2 tron prop_object_release(cfg);
187 1.2 tron return;
188 1.2 tron }
189 1.2 tron
190 1.2 tron prop_object_release(cfg);
191 1.2 tron
192 1.2 tron fd = open(new_key_file, O_WRONLY|O_TRUNC|O_CREAT|O_EXLOCK, 0600);
193 1.1 gdamore if (fd < 0) {
194 1.2 tron syslog(LOG_ERR, "Cannot open new keyfile %s. %s (%d)",
195 1.1 gdamore key_file, strerror(errno), errno);
196 1.1 gdamore
197 1.2 tron free(xml);
198 1.1 gdamore return;
199 1.1 gdamore }
200 1.1 gdamore
201 1.2 tron len = strlen(xml);
202 1.2 tron if (write(fd, xml, len) != len) {
203 1.2 tron syslog(LOG_ERR, "Write of keyfile failed. %s (%d)",
204 1.2 tron strerror(errno), errno);
205 1.2 tron
206 1.2 tron free(xml);
207 1.2 tron close(fd);
208 1.2 tron unlink(new_key_file);
209 1.2 tron return;
210 1.2 tron }
211 1.1 gdamore
212 1.2 tron free(xml);
213 1.1 gdamore close(fd);
214 1.2 tron
215 1.2 tron if (rename(new_key_file, key_file) < 0) {
216 1.2 tron syslog(LOG_ERR, "rename(%s, %s) failed. %s (%d)",
217 1.2 tron new_key_file, key_file, strerror(errno), errno);
218 1.2 tron
219 1.2 tron unlink(new_key_file);
220 1.2 tron }
221 1.1 gdamore }
222