ncpl_bind.c revision 90868
182900Sjake/*
282900Sjake * Copyright (c) 1999, Boris Popov
382900Sjake * All rights reserved.
482900Sjake *
582900Sjake * Redistribution and use in source and binary forms, with or without
682900Sjake * modification, are permitted provided that the following conditions
782900Sjake * are met:
882900Sjake * 1. Redistributions of source code must retain the above copyright
982900Sjake *    notice, this list of conditions and the following disclaimer.
1082900Sjake * 2. Redistributions in binary form must reproduce the above copyright
1182900Sjake *    notice, this list of conditions and the following disclaimer in the
1282900Sjake *    documentation and/or other materials provided with the distribution.
1382900Sjake * 3. All advertising materials mentioning features or use of this software
1482900Sjake *    must display the following acknowledgement:
1582900Sjake *    This product includes software developed by Boris Popov.
1682900Sjake * 4. Neither the name of the author nor the names of any co-contributors
1782900Sjake *    may be used to endorse or promote products derived from this software
1882900Sjake *    without specific prior written permission.
1982900Sjake *
2082900Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2182900Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2282900Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2382900Sjake * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2482900Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2582900Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2682900Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2782900Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2882900Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2982900Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3082900Sjake * SUCH DAMAGE.
3182900Sjake */
3282900Sjake
3382900Sjake#include <sys/cdefs.h>
3482900Sjake__FBSDID("$FreeBSD: head/lib/libncp/ncpl_bind.c 90868 2002-02-18 20:35:27Z mike $");
35153175Smarius
36153175Smarius#include <sys/types.h>
3793949Sjake#include <arpa/inet.h>
3882900Sjake#include <errno.h>
39203838Smarius#include <string.h>
4093949Sjake#include <netncp/ncp_lib.h>
4193949Sjake
4293949Sjakestatic void nw_passencrypt(char *old, char *new, char *out);
4382900Sjake
4493949Sjakeint
4582900Sjakencp_get_bindery_object_id(NWCONN_HANDLE connid, u_int16_t object_type,
4682900Sjake	const char *object_name, struct ncp_bindery_object *target)
4782900Sjake{
48114071Sobrien	int error;
4982900Sjake	DECLARE_RQ;
5093949Sjake
5182900Sjake	ncp_init_request_s(conn, 53);
52114071Sobrien	ncp_add_word_hl(conn, object_type);
5384177Sjake	ncp_add_pstring(conn, object_name);
5484177Sjake
5584177Sjake	if ((error = ncp_request(connid, 23, conn)) != 0) {
5682900Sjake		return error;
5782900Sjake	}
5882900Sjake	if (conn->rpsize < 54) {
5982900Sjake		return EACCES;
6093949Sjake	}
61243046Sjeff	target->object_id = ncp_reply_dword_hl(conn, 0);
6282900Sjake	target->object_type = ncp_reply_word_hl(conn, 4);
6382900Sjake	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
6493949Sjake	return 0;
6593949Sjake}
66203838Smarius
6793949Sjakeint
6893949Sjakencp_read_property_value(NWCONN_HANDLE connid, int object_type,
6993949Sjake	const char *object_name, int segment, const char *prop_name,
7093949Sjake	struct nw_property *target)
7182900Sjake{
7282900Sjake	int error;
73222828Smarius	struct ncp_buf conn;
74222828Smarius	ncp_init_request_s(&conn, 61);
75222828Smarius	ncp_add_word_hl(&conn, object_type);
7682900Sjake	ncp_add_pstring(&conn, object_name);
7793949Sjake	ncp_add_byte(&conn, segment);
78222828Smarius	ncp_add_pstring(&conn, prop_name);
79222828Smarius
80222828Smarius	if ((error = ncp_request(connid,23,&conn)) != 0) {
81222828Smarius		return error;
82222828Smarius	}
83222828Smarius	memcpy(&(target->value), ncp_reply_data(&conn, 0), 128);
84222828Smarius	target->more_flag = ncp_reply_byte(&conn, 128);
85222828Smarius	target->property_flag = ncp_reply_byte(&conn, 129);
86222828Smarius	return 0;
87222828Smarius}
88222828Smarius
89222828Smariusint
90222828Smariusncp_scan_bindery_object(NWCONN_HANDLE connid, u_int32_t last_id,
91222828Smarius	u_int16_t object_type, char *search_string,
92222828Smarius	struct ncp_bindery_object *target)
93222828Smarius{
94222828Smarius	int error;
95222828Smarius	DECLARE_RQ;
96222828Smarius
97222828Smarius	ncp_init_request_s(conn, 55);
98222828Smarius	ncp_add_dword_hl(conn, last_id);
9993949Sjake	ncp_add_word_hl(conn, object_type);
100222828Smarius	ncp_add_pstring(conn, search_string);
101222828Smarius	error = ncp_request(connid, 23, conn);
102222828Smarius	if (error) return error;
103222828Smarius	target->object_id = ncp_reply_dword_hl(conn, 0);
10482900Sjake	target->object_type = ncp_reply_word_hl(conn, 4);
10582900Sjake	memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN);
10682900Sjake	target->object_flags = ncp_reply_byte(conn, 54);
10782900Sjake	target->object_security = ncp_reply_byte(conn, 55);
10882900Sjake	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