152153Sbp/*
252153Sbp * Copyright (c) 1999, Boris Popov
352153Sbp * All rights reserved.
452153Sbp *
552153Sbp * Redistribution and use in source and binary forms, with or without
652153Sbp * modification, are permitted provided that the following conditions
752153Sbp * are met:
852153Sbp * 1. Redistributions of source code must retain the above copyright
952153Sbp *    notice, this list of conditions and the following disclaimer.
1052153Sbp * 2. Redistributions in binary form must reproduce the above copyright
1152153Sbp *    notice, this list of conditions and the following disclaimer in the
1252153Sbp *    documentation and/or other materials provided with the distribution.
13165920Simp * 3. Neither the name of the author nor the names of any co-contributors
1452153Sbp *    may be used to endorse or promote products derived from this software
1552153Sbp *    without specific prior written permission.
1652153Sbp *
1752153Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1852153Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1952153Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2052153Sbp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2152153Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2252153Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2352153Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2452153Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2552153Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2652153Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2752153Sbp * SUCH DAMAGE.
2852153Sbp */
2984213Sdillon
3084213Sdillon#include <sys/cdefs.h>
3184213Sdillon__FBSDID("$FreeBSD$");
3284213Sdillon
3352153Sbp#include <sys/types.h>
3490868Smike#include <arpa/inet.h>
3552153Sbp#include <errno.h>
3652153Sbp#include <string.h>
3752153Sbp#include <netncp/ncp_lib.h>
3852153Sbp
3952153Sbpstatic void nw_passencrypt(char *old, char *new, char *out);
4052153Sbp
4152153Sbpint
4252704Sbpncp_get_bindery_object_id(NWCONN_HANDLE connid, u_int16_t object_type,
4352704Sbp	const char *object_name, struct ncp_bindery_object *target)
4452704Sbp{
4552153Sbp	int error;
4652153Sbp	DECLARE_RQ;
4752153Sbp
4852153Sbp	ncp_init_request_s(conn, 53);
4952153Sbp	ncp_add_word_hl(conn, object_type);
5052153Sbp	ncp_add_pstring(conn, object_name);
5152153Sbp
5252153Sbp	if ((error = ncp_request(connid, 23, conn)) != 0) {
5352153Sbp		return error;
5452153Sbp	}
5552153Sbp	if (conn->rpsize < 54) {
5652153Sbp		return EACCES;
5752153Sbp	}
5852153Sbp	target->object_id = ncp_reply_dword_hl(conn, 0);
5952153Sbp	target->object_type = ncp_reply_word_hl(conn, 4);
6052153Sbp	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
6152153Sbp	return 0;
6252153Sbp}
6352153Sbp
6452153Sbpint
6552704Sbpncp_read_property_value(NWCONN_HANDLE connid, int object_type,
6652704Sbp	const char *object_name, int segment, const char *prop_name,
6752704Sbp	struct nw_property *target)
6852153Sbp{
6952153Sbp	int error;
7052153Sbp	struct ncp_buf conn;
7152153Sbp	ncp_init_request_s(&conn, 61);
7252153Sbp	ncp_add_word_hl(&conn, object_type);
7352153Sbp	ncp_add_pstring(&conn, object_name);
7452153Sbp	ncp_add_byte(&conn, segment);
7552153Sbp	ncp_add_pstring(&conn, prop_name);
7652153Sbp
7752153Sbp	if ((error = ncp_request(connid,23,&conn)) != 0) {
7852153Sbp		return error;
7952153Sbp	}
8052153Sbp	memcpy(&(target->value), ncp_reply_data(&conn, 0), 128);
8152153Sbp	target->more_flag = ncp_reply_byte(&conn, 128);
8252153Sbp	target->property_flag = ncp_reply_byte(&conn, 129);
8352153Sbp	return 0;
8452153Sbp}
8552153Sbp
8652153Sbpint
8752704Sbpncp_scan_bindery_object(NWCONN_HANDLE connid, u_int32_t last_id,
8852704Sbp	u_int16_t object_type, char *search_string,
8952704Sbp	struct ncp_bindery_object *target)
9052153Sbp{
9152153Sbp	int error;
9252153Sbp	DECLARE_RQ;
9352153Sbp
9452153Sbp	ncp_init_request_s(conn, 55);
9552153Sbp	ncp_add_dword_hl(conn, last_id);
9652153Sbp	ncp_add_word_hl(conn, object_type);
9752153Sbp	ncp_add_pstring(conn, search_string);
9852153Sbp	error = ncp_request(connid, 23, conn);
9952153Sbp	if (error) return error;
10052153Sbp	target->object_id = ncp_reply_dword_hl(conn, 0);
10152153Sbp	target->object_type = ncp_reply_word_hl(conn, 4);
10252153Sbp	memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN);
10352153Sbp	target->object_flags = ncp_reply_byte(conn, 54);
10452153Sbp	target->object_security = ncp_reply_byte(conn, 55);
10552153Sbp	target->object_has_prop = ncp_reply_byte(conn, 56);
10652153Sbp	return 0;
10752153Sbp}
10852153Sbp
10952153Sbpint
11052704Sbpncp_get_bindery_object_name(NWCONN_HANDLE connid, u_int32_t object_id,
11152704Sbp	struct ncp_bindery_object *target)
11252704Sbp{
11352153Sbp	int error;
11452153Sbp	DECLARE_RQ;
11552153Sbp
11652153Sbp	ncp_init_request_s(conn, 54);
11752153Sbp	ncp_add_dword_hl(conn, object_id);
11852153Sbp	if ((error = ncp_request(connid, 23, conn)) != 0)
11952153Sbp		return error;
12052153Sbp	target->object_id = ncp_reply_dword_hl(conn, 0);
12152153Sbp	target->object_type = ncp_reply_word_hl(conn, 4);
12252153Sbp	memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
12352153Sbp	return 0;
12452153Sbp}
12552153Sbp
12652153Sbpint
12752153Sbpncp_change_obj_passwd(NWCONN_HANDLE connid,
12852153Sbp	const struct ncp_bindery_object *object,
12952153Sbp	const u_char *key,
13052153Sbp	const u_char *oldpasswd,
13152153Sbp	const u_char *newpasswd)
13252153Sbp{
13352153Sbp	long id = htonl(object->object_id);
13452153Sbp	u_char cryptkey[8];
13552153Sbp	u_char newpwd[16];	/* new passwd as stored by server */
13652153Sbp	u_char oldpwd[16];	/* old passwd as stored by server */
13752153Sbp	u_char len;
13852153Sbp	DECLARE_RQ;
13952153Sbp
14052153Sbp	memcpy(cryptkey, key, 8);
14152153Sbp	nw_keyhash((u_char *)&id, oldpasswd, strlen(oldpasswd), oldpwd);
14252153Sbp	nw_keyhash((u_char *)&id, newpasswd, strlen(newpasswd), newpwd);
14352153Sbp	nw_encrypt(cryptkey, oldpwd, cryptkey);
14452153Sbp	nw_passencrypt(oldpwd, newpwd, newpwd);
14552153Sbp	nw_passencrypt(oldpwd + 8, newpwd + 8, newpwd + 8);
14652153Sbp	if ((len = strlen(newpasswd)) > 63) {
14752153Sbp		len = 63;
14852153Sbp	}
14952153Sbp	len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40;
15052153Sbp
15152153Sbp	ncp_init_request_s(conn, 75);
15252153Sbp	ncp_add_mem(conn, cryptkey, 8);
15352153Sbp	ncp_add_word_hl(conn, object->object_type);
15452153Sbp	ncp_add_pstring(conn, object->object_name);
15552153Sbp	ncp_add_byte(conn, len);
15652153Sbp	ncp_add_mem(conn, newpwd, 16);
15752153Sbp	return ncp_request(connid, 23, conn);
15852153Sbp}
15952153Sbp
16052153Sbp/*
16152153Sbp * target is a 8-byte buffer
16252153Sbp */
16352153Sbpint
16452153Sbpncp_get_encryption_key(NWCONN_HANDLE cH, char *target) {
16552153Sbp	int error;
16652153Sbp	DECLARE_RQ;
16752153Sbp
16852153Sbp	ncp_init_request_s(conn, 23);
16952153Sbp
17052153Sbp	error = ncp_request(cH, 23, conn);
17152153Sbp	if (error)
17252153Sbp		return error;
17352153Sbp	if (conn->rpsize < 8)
17452153Sbp		return EACCES;
17552153Sbp	memcpy(target, ncp_reply_data(conn, 0), 8);
17652153Sbp	return 0;
17752153Sbp}
17852153Sbp
17952153Sbpint
18052153Sbpncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd,
18152704Sbp	struct ncp_bindery_object *objinfo)
18252704Sbp{
18352153Sbp	u_long id = htonl(objinfo->object_id);
18452153Sbp	u_char cryptkey[8];
18552153Sbp	u_char buf[128];
18652153Sbp	DECLARE_RQ;
18752153Sbp
18852153Sbp	nw_keyhash((u_char *)&id, passwd, strlen(passwd), buf);
18952153Sbp	nw_encrypt(key, buf, cryptkey);
19052153Sbp
19152153Sbp	ncp_init_request_s(conn, 74);
19252153Sbp	ncp_add_mem(conn, cryptkey, sizeof(cryptkey));
19352153Sbp	ncp_add_word_hl(conn, objinfo->object_type);
19452153Sbp	ncp_add_pstring(conn, objinfo->object_name);
19552153Sbp
19652153Sbp	return ncp_request(cH, 23, conn);
19752153Sbp}
19852153Sbp
19952153Sbpstatic char passkeys[256 + 16] = {
20052153Sbp	0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
20152153Sbp	0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
20252153Sbp	0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
20352153Sbp	0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
20452153Sbp	0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
20552153Sbp	0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
20652153Sbp	0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
20752153Sbp	0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
20852153Sbp	0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
20952153Sbp	0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
21052153Sbp	0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
21152153Sbp	0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
21252153Sbp	0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
21352153Sbp	0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
21452153Sbp	0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
21552153Sbp	0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
21652153Sbp	0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
21752153Sbp	0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
21852153Sbp	0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
21952153Sbp	0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
22052153Sbp	0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
22152153Sbp	0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
22252153Sbp	0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
22352153Sbp	0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
22452153Sbp	0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
22552153Sbp	0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
22652153Sbp	0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
22752153Sbp	0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
22852153Sbp	0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
22952153Sbp	0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
23052153Sbp	0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
23152153Sbp	0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
23252153Sbp	0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
23352153Sbp	0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08
23452153Sbp};
23552153Sbp
23652153Sbpstatic void
23752153Sbpnw_passencrypt(char *old, char *new, char *out)
23852153Sbp{
23952153Sbp	char *p, v;
24052153Sbp	char copy[8];
24152153Sbp	int i, di, ax;
24252153Sbp
24352153Sbp#define HIGH(x)	(((x) >> 4) & 0xf)
24452153Sbp#define LOW(x)	((x) & 0xf)
24552153Sbp	memcpy(copy, new, 8);
24652153Sbp
24752153Sbp	for (i = 0; i < 16; i++) {
24852153Sbp		for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) {
24952153Sbp			v = copy[di] ^ *p;
25052153Sbp			copy[di] = (passkeys[HIGH(v) + ax + 0x10] << 4) |
25152153Sbp				   passkeys[LOW(v) + ax];
25252153Sbp		}
25352153Sbp		v = old[7];
25452153Sbp		for (p = old + 7; p > old; p--) {
25552153Sbp			*p = HIGH(p[-1]) | ((*p) << 4);
25652153Sbp		}
25752153Sbp		*old = HIGH(v) | (*old) << 4;
25852153Sbp		bzero(out, 8);
25952153Sbp
26052153Sbp		for (di = 0; di < 16; di++) {
26152153Sbp			v = passkeys[di + 0x100];
26252153Sbp			v = (v & 1) ? HIGH(copy[v / 2]) : LOW(copy[v / 2]);
26352153Sbp			out[di / 2] |= ((di & 1) ? v << 4 : v);
26452153Sbp		}
26552153Sbp		memcpy(copy, out, 8);
26652153Sbp	}
26752153Sbp}
268