ncpl_bind.c revision 90868
1/*
2 * Copyright (c) 1999, Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *    This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/lib/libncp/ncpl_bind.c 90868 2002-02-18 20:35:27Z mike $");
35
36#include <sys/types.h>
37#include <arpa/inet.h>
38#include <errno.h>
39#include <string.h>
40#include <netncp/ncp_lib.h>
41
42static void nw_passencrypt(char *old, char *new, char *out);
43
44int
45ncp_get_bindery_object_id(NWCONN_HANDLE connid, u_int16_t object_type,
46	const char *object_name, struct ncp_bindery_object *target)
47{
48	int error;
49	DECLARE_RQ;
50
51	ncp_init_request_s(conn, 53);
52	ncp_add_word_hl(conn, object_type);
53	ncp_add_pstring(conn, object_name);
54
55	if ((error = ncp_request(connid, 23, conn)) != 0) {
56		return error;
57	}
58	if (conn->rpsize < 54) {
59		return EACCES;
60	}
61	target->object_id = ncp_reply_dword_hl(conn, 0);
62	target->object_type = ncp_reply_word_hl(conn, 4);
63	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
64	return 0;
65}
66
67int
68ncp_read_property_value(NWCONN_HANDLE connid, int object_type,
69	const char *object_name, int segment, const char *prop_name,
70	struct nw_property *target)
71{
72	int error;
73	struct ncp_buf conn;
74	ncp_init_request_s(&conn, 61);
75	ncp_add_word_hl(&conn, object_type);
76	ncp_add_pstring(&conn, object_name);
77	ncp_add_byte(&conn, segment);
78	ncp_add_pstring(&conn, prop_name);
79
80	if ((error = ncp_request(connid,23,&conn)) != 0) {
81		return error;
82	}
83	memcpy(&(target->value), ncp_reply_data(&conn, 0), 128);
84	target->more_flag = ncp_reply_byte(&conn, 128);
85	target->property_flag = ncp_reply_byte(&conn, 129);
86	return 0;
87}
88
89int
90ncp_scan_bindery_object(NWCONN_HANDLE connid, u_int32_t last_id,
91	u_int16_t object_type, char *search_string,
92	struct ncp_bindery_object *target)
93{
94	int error;
95	DECLARE_RQ;
96
97	ncp_init_request_s(conn, 55);
98	ncp_add_dword_hl(conn, last_id);
99	ncp_add_word_hl(conn, object_type);
100	ncp_add_pstring(conn, search_string);
101	error = ncp_request(connid, 23, conn);
102	if (error) return error;
103	target->object_id = ncp_reply_dword_hl(conn, 0);
104	target->object_type = ncp_reply_word_hl(conn, 4);
105	memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN);
106	target->object_flags = ncp_reply_byte(conn, 54);
107	target->object_security = ncp_reply_byte(conn, 55);
108	target->object_has_prop = ncp_reply_byte(conn, 56);
109	return 0;
110}
111
112int
113ncp_get_bindery_object_name(NWCONN_HANDLE connid, u_int32_t object_id,
114	struct ncp_bindery_object *target)
115{
116	int error;
117	DECLARE_RQ;
118
119	ncp_init_request_s(conn, 54);
120	ncp_add_dword_hl(conn, object_id);
121	if ((error = ncp_request(connid, 23, conn)) != 0)
122		return error;
123	target->object_id = ncp_reply_dword_hl(conn, 0);
124	target->object_type = ncp_reply_word_hl(conn, 4);
125	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
126	return 0;
127}
128
129int
130ncp_change_obj_passwd(NWCONN_HANDLE connid,
131	const struct ncp_bindery_object *object,
132	const u_char *key,
133	const u_char *oldpasswd,
134	const u_char *newpasswd)
135{
136	long id = htonl(object->object_id);
137	u_char cryptkey[8];
138	u_char newpwd[16];	/* new passwd as stored by server */
139	u_char oldpwd[16];	/* old passwd as stored by server */
140	u_char len;
141	DECLARE_RQ;
142
143	memcpy(cryptkey, key, 8);
144	nw_keyhash((u_char *)&id, oldpasswd, strlen(oldpasswd), oldpwd);
145	nw_keyhash((u_char *)&id, newpasswd, strlen(newpasswd), newpwd);
146	nw_encrypt(cryptkey, oldpwd, cryptkey);
147	nw_passencrypt(oldpwd, newpwd, newpwd);
148	nw_passencrypt(oldpwd + 8, newpwd + 8, newpwd + 8);
149	if ((len = strlen(newpasswd)) > 63) {
150		len = 63;
151	}
152	len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40;
153
154	ncp_init_request_s(conn, 75);
155	ncp_add_mem(conn, cryptkey, 8);
156	ncp_add_word_hl(conn, object->object_type);
157	ncp_add_pstring(conn, object->object_name);
158	ncp_add_byte(conn, len);
159	ncp_add_mem(conn, newpwd, 16);
160	return ncp_request(connid, 23, conn);
161}
162
163/*
164 * target is a 8-byte buffer
165 */
166int
167ncp_get_encryption_key(NWCONN_HANDLE cH, char *target) {
168	int error;
169	DECLARE_RQ;
170
171	ncp_init_request_s(conn, 23);
172
173	error = ncp_request(cH, 23, conn);
174	if (error)
175		return error;
176	if (conn->rpsize < 8)
177		return EACCES;
178	memcpy(target, ncp_reply_data(conn, 0), 8);
179	return 0;
180}
181
182int
183ncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd,
184	struct ncp_bindery_object *objinfo)
185{
186	u_long id = htonl(objinfo->object_id);
187	u_char cryptkey[8];
188	u_char buf[128];
189	DECLARE_RQ;
190
191	nw_keyhash((u_char *)&id, passwd, strlen(passwd), buf);
192	nw_encrypt(key, buf, cryptkey);
193
194	ncp_init_request_s(conn, 74);
195	ncp_add_mem(conn, cryptkey, sizeof(cryptkey));
196	ncp_add_word_hl(conn, objinfo->object_type);
197	ncp_add_pstring(conn, objinfo->object_name);
198
199	return ncp_request(cH, 23, conn);
200}
201
202static char passkeys[256 + 16] = {
203	0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
204	0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
205	0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
206	0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
207	0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
208	0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
209	0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
210	0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
211	0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
212	0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
213	0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
214	0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
215	0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
216	0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
217	0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
218	0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
219	0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
220	0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
221	0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
222	0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
223	0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
224	0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
225	0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
226	0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
227	0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
228	0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
229	0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
230	0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
231	0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
232	0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
233	0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
234	0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
235	0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
236	0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08
237};
238
239static void
240nw_passencrypt(char *old, char *new, char *out)
241{
242	char *p, v;
243	char copy[8];
244	int i, di, ax;
245
246#define HIGH(x)	(((x) >> 4) & 0xf)
247#define LOW(x)	((x) & 0xf)
248	memcpy(copy, new, 8);
249
250	for (i = 0; i < 16; i++) {
251		for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) {
252			v = copy[di] ^ *p;
253			copy[di] = (passkeys[HIGH(v) + ax + 0x10] << 4) |
254				   passkeys[LOW(v) + ax];
255		}
256		v = old[7];
257		for (p = old + 7; p > old; p--) {
258			*p = HIGH(p[-1]) | ((*p) << 4);
259		}
260		*old = HIGH(v) | (*old) << 4;
261		bzero(out, 8);
262
263		for (di = 0; di < 16; di++) {
264			v = passkeys[di + 0x100];
265			v = (v & 1) ? HIGH(copy[v / 2]) : LOW(copy[v / 2]);
266			out[di / 2] |= ((di & 1) ? v << 4 : v);
267		}
268		memcpy(copy, out, 8);
269	}
270}
271