ncpl_bind.c revision 52153
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 * $FreeBSD: head/lib/libncp/ncpl_bind.c 52153 1999-10-12 11:56:41Z bp $
33 */
34#include <sys/types.h>
35#include <errno.h>
36#include <string.h>
37#include <netncp/ncp_lib.h>
38
39static void nw_passencrypt(char *old, char *new, char *out);
40
41int
42ncp_get_bindery_object_id(int connid, u_int16_t object_type, const char *object_name,
43			  struct ncp_bindery_object *target) {
44	int error;
45	DECLARE_RQ;
46
47	ncp_init_request_s(conn, 53);
48	ncp_add_word_hl(conn, object_type);
49	ncp_add_pstring(conn, object_name);
50
51	if ((error = ncp_request(connid, 23, conn)) != 0) {
52		return error;
53	}
54	if (conn->rpsize < 54) {
55		return EACCES;
56	}
57	target->object_id = ncp_reply_dword_hl(conn, 0);
58	target->object_type = ncp_reply_word_hl(conn, 4);
59	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
60	return 0;
61}
62
63int
64ncp_read_property_value(int connid, int object_type, const char *object_name,
65			int segment, const char *prop_name,
66			struct nw_property *target)
67{
68	int error;
69	struct ncp_buf conn;
70	ncp_init_request_s(&conn, 61);
71	ncp_add_word_hl(&conn, object_type);
72	ncp_add_pstring(&conn, object_name);
73	ncp_add_byte(&conn, segment);
74	ncp_add_pstring(&conn, prop_name);
75
76	if ((error = ncp_request(connid,23,&conn)) != 0) {
77		return error;
78	}
79	memcpy(&(target->value), ncp_reply_data(&conn, 0), 128);
80	target->more_flag = ncp_reply_byte(&conn, 128);
81	target->property_flag = ncp_reply_byte(&conn, 129);
82	return 0;
83}
84
85int
86ncp_scan_bindery_object(int connid, u_int32_t last_id, u_int16_t object_type,
87	char *search_string, struct ncp_bindery_object *target)
88{
89	int error;
90	DECLARE_RQ;
91
92	ncp_init_request_s(conn, 55);
93	ncp_add_dword_hl(conn, last_id);
94	ncp_add_word_hl(conn, object_type);
95	ncp_add_pstring(conn, search_string);
96	error = ncp_request(connid, 23, conn);
97	if (error) return error;
98	target->object_id = ncp_reply_dword_hl(conn, 0);
99	target->object_type = ncp_reply_word_hl(conn, 4);
100	memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN);
101	target->object_flags = ncp_reply_byte(conn, 54);
102	target->object_security = ncp_reply_byte(conn, 55);
103	target->object_has_prop = ncp_reply_byte(conn, 56);
104	return 0;
105}
106
107int
108ncp_get_bindery_object_name(int connid, u_int32_t object_id,
109			    struct ncp_bindery_object *target) {
110	int error;
111	DECLARE_RQ;
112
113	ncp_init_request_s(conn, 54);
114	ncp_add_dword_hl(conn, object_id);
115	if ((error = ncp_request(connid, 23, conn)) != 0)
116		return error;
117	target->object_id = ncp_reply_dword_hl(conn, 0);
118	target->object_type = ncp_reply_word_hl(conn, 4);
119	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
120	return 0;
121}
122
123int
124ncp_change_obj_passwd(NWCONN_HANDLE connid,
125	const struct ncp_bindery_object *object,
126	const u_char *key,
127	const u_char *oldpasswd,
128	const u_char *newpasswd)
129{
130	long id = htonl(object->object_id);
131	u_char cryptkey[8];
132	u_char newpwd[16];	/* new passwd as stored by server */
133	u_char oldpwd[16];	/* old passwd as stored by server */
134	u_char len;
135	DECLARE_RQ;
136
137	memcpy(cryptkey, key, 8);
138	nw_keyhash((u_char *)&id, oldpasswd, strlen(oldpasswd), oldpwd);
139	nw_keyhash((u_char *)&id, newpasswd, strlen(newpasswd), newpwd);
140	nw_encrypt(cryptkey, oldpwd, cryptkey);
141	nw_passencrypt(oldpwd, newpwd, newpwd);
142	nw_passencrypt(oldpwd + 8, newpwd + 8, newpwd + 8);
143	if ((len = strlen(newpasswd)) > 63) {
144		len = 63;
145	}
146	len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40;
147
148	ncp_init_request_s(conn, 75);
149	ncp_add_mem(conn, cryptkey, 8);
150	ncp_add_word_hl(conn, object->object_type);
151	ncp_add_pstring(conn, object->object_name);
152	ncp_add_byte(conn, len);
153	ncp_add_mem(conn, newpwd, 16);
154	return ncp_request(connid, 23, conn);
155}
156
157/*
158 * target is a 8-byte buffer
159 */
160int
161ncp_get_encryption_key(NWCONN_HANDLE cH, char *target) {
162	int error;
163	DECLARE_RQ;
164
165	ncp_init_request_s(conn, 23);
166
167	error = ncp_request(cH, 23, conn);
168	if (error)
169		return error;
170	if (conn->rpsize < 8)
171		return EACCES;
172	memcpy(target, ncp_reply_data(conn, 0), 8);
173	return 0;
174}
175
176int
177ncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd,
178			    struct ncp_bindery_object *objinfo) {
179	u_long id = htonl(objinfo->object_id);
180	u_char cryptkey[8];
181	u_char buf[128];
182	DECLARE_RQ;
183
184	nw_keyhash((u_char *)&id, passwd, strlen(passwd), buf);
185	nw_encrypt(key, buf, cryptkey);
186
187	ncp_init_request_s(conn, 74);
188	ncp_add_mem(conn, cryptkey, sizeof(cryptkey));
189	ncp_add_word_hl(conn, objinfo->object_type);
190	ncp_add_pstring(conn, objinfo->object_name);
191
192	return ncp_request(cH, 23, conn);
193}
194
195static char passkeys[256 + 16] = {
196	0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
197	0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
198	0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
199	0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
200	0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
201	0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
202	0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
203	0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
204	0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
205	0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
206	0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
207	0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
208	0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
209	0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
210	0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
211	0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
212	0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
213	0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
214	0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
215	0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
216	0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
217	0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
218	0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
219	0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
220	0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
221	0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
222	0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
223	0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
224	0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
225	0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
226	0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
227	0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
228	0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
229	0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08
230};
231
232static void
233nw_passencrypt(char *old, char *new, char *out)
234{
235	char *p, v;
236	char copy[8];
237	int i, di, ax;
238
239#define HIGH(x)	(((x) >> 4) & 0xf)
240#define LOW(x)	((x) & 0xf)
241	memcpy(copy, new, 8);
242
243	for (i = 0; i < 16; i++) {
244		for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) {
245			v = copy[di] ^ *p;
246			copy[di] = (passkeys[HIGH(v) + ax + 0x10] << 4) |
247				   passkeys[LOW(v) + ax];
248		}
249		v = old[7];
250		for (p = old + 7; p > old; p--) {
251			*p = HIGH(p[-1]) | ((*p) << 4);
252		}
253		*old = HIGH(v) | (*old) << 4;
254		bzero(out, 8);
255
256		for (di = 0; di < 16; di++) {
257			v = passkeys[di + 0x100];
258			v = (v & 1) ? HIGH(copy[v / 2]) : LOW(copy[v / 2]);
259			out[di / 2] |= ((di & 1) ? v << 4 : v);
260		}
261		memcpy(copy, out, 8);
262	}
263}
264