11638Srgrimes/* 21638Srgrimes * Copyright (c) 1999, Boris Popov 31638Srgrimes * All rights reserved. 41638Srgrimes * 51638Srgrimes * Redistribution and use in source and binary forms, with or without 61638Srgrimes * modification, are permitted provided that the following conditions 71638Srgrimes * are met: 81638Srgrimes * 1. Redistributions of source code must retain the above copyright 91638Srgrimes * notice, this list of conditions and the following disclaimer. 101638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111638Srgrimes * notice, this list of conditions and the following disclaimer in the 121638Srgrimes * documentation and/or other materials provided with the distribution. 131638Srgrimes * 3. Neither the name of the author nor the names of any co-contributors 141638Srgrimes * may be used to endorse or promote products derived from this software 151638Srgrimes * without specific prior written permission. 161638Srgrimes * 171638Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 181638Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191638Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201638Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 211638Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221638Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231638Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241638Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251638Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261638Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271638Srgrimes * SUCH DAMAGE. 281638Srgrimes */ 291638Srgrimes 301638Srgrimes#include <sys/cdefs.h> 311638Srgrimes__FBSDID("$FreeBSD$"); 321638Srgrimes 331638Srgrimes#include <sys/types.h> 341638Srgrimes#include <arpa/inet.h> 351638Srgrimes#include <errno.h> 361638Srgrimes#include <string.h> 371638Srgrimes#include <netncp/ncp_lib.h> 381638Srgrimes 391638Srgrimesstatic void nw_passencrypt(char *old, char *new, char *out); 401638Srgrimes 411638Srgrimesint 421638Srgrimesncp_get_bindery_object_id(NWCONN_HANDLE connid, u_int16_t object_type, 431638Srgrimes const char *object_name, struct ncp_bindery_object *target) 441638Srgrimes{ 451638Srgrimes int error; 461638Srgrimes DECLARE_RQ; 471638Srgrimes 481638Srgrimes ncp_init_request_s(conn, 53); 491638Srgrimes ncp_add_word_hl(conn, object_type); 501638Srgrimes ncp_add_pstring(conn, object_name); 511638Srgrimes 521638Srgrimes if ((error = ncp_request(connid, 23, conn)) != 0) { 531638Srgrimes return error; 541638Srgrimes } 551638Srgrimes if (conn->rpsize < 54) { 561638Srgrimes return EACCES; 571638Srgrimes } 581638Srgrimes target->object_id = ncp_reply_dword_hl(conn, 0); 591638Srgrimes target->object_type = ncp_reply_word_hl(conn, 4); 601638Srgrimes memcpy(target->object_name, ncp_reply_data(conn, 6), 48); 611638Srgrimes return 0; 621638Srgrimes} 631638Srgrimes 641638Srgrimesint 651638Srgrimesncp_read_property_value(NWCONN_HANDLE connid, int object_type, 661638Srgrimes const char *object_name, int segment, const char *prop_name, 671638Srgrimes struct nw_property *target) 681638Srgrimes{ 691638Srgrimes int error; 701638Srgrimes struct ncp_buf conn; 711638Srgrimes ncp_init_request_s(&conn, 61); 721638Srgrimes ncp_add_word_hl(&conn, object_type); 731638Srgrimes ncp_add_pstring(&conn, object_name); 741638Srgrimes ncp_add_byte(&conn, segment); 751638Srgrimes ncp_add_pstring(&conn, prop_name); 761638Srgrimes 771638Srgrimes if ((error = ncp_request(connid,23,&conn)) != 0) { 781638Srgrimes return error; 791638Srgrimes } 801638Srgrimes memcpy(&(target->value), ncp_reply_data(&conn, 0), 128); 811638Srgrimes target->more_flag = ncp_reply_byte(&conn, 128); 821638Srgrimes target->property_flag = ncp_reply_byte(&conn, 129); 831638Srgrimes return 0; 841638Srgrimes} 851638Srgrimes 861638Srgrimesint 871638Srgrimesncp_scan_bindery_object(NWCONN_HANDLE connid, u_int32_t last_id, 881638Srgrimes u_int16_t object_type, char *search_string, 891638Srgrimes struct ncp_bindery_object *target) 9016398Swosch{ 9116398Swosch int error; 9216398Swosch DECLARE_RQ; 931638Srgrimes 941638Srgrimes ncp_init_request_s(conn, 55); 951638Srgrimes ncp_add_dword_hl(conn, last_id); 961638Srgrimes ncp_add_word_hl(conn, object_type); 971638Srgrimes ncp_add_pstring(conn, search_string); 981638Srgrimes error = ncp_request(connid, 23, conn); 991638Srgrimes if (error) return error; 1001638Srgrimes target->object_id = ncp_reply_dword_hl(conn, 0); 1011638Srgrimes target->object_type = ncp_reply_word_hl(conn, 4); 1021638Srgrimes memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN); 1031638Srgrimes target->object_flags = ncp_reply_byte(conn, 54); 1041638Srgrimes target->object_security = ncp_reply_byte(conn, 55); 1051638Srgrimes target->object_has_prop = ncp_reply_byte(conn, 56); 1061638Srgrimes return 0; 1071638Srgrimes} 1081638Srgrimes 1091638Srgrimesint 1101638Srgrimesncp_get_bindery_object_name(NWCONN_HANDLE connid, u_int32_t object_id, 1111638Srgrimes struct ncp_bindery_object *target) 1121638Srgrimes{ 1131638Srgrimes int error; 1141638Srgrimes DECLARE_RQ; 1151638Srgrimes 1161638Srgrimes ncp_init_request_s(conn, 54); 1171638Srgrimes ncp_add_dword_hl(conn, object_id); 1181638Srgrimes if ((error = ncp_request(connid, 23, conn)) != 0) 1191638Srgrimes return error; 1201638Srgrimes target->object_id = ncp_reply_dword_hl(conn, 0); 1211638Srgrimes target->object_type = ncp_reply_word_hl(conn, 4); 1221638Srgrimes memcpy(target->object_name, ncp_reply_data(conn, 6), 48); 1231638Srgrimes return 0; 1241638Srgrimes} 1251638Srgrimes 1261638Srgrimesint 1271638Srgrimesncp_change_obj_passwd(NWCONN_HANDLE connid, 1281638Srgrimes const struct ncp_bindery_object *object, 1291638Srgrimes const u_char *key, 1301638Srgrimes const u_char *oldpasswd, 13116398Swosch const u_char *newpasswd) 1321638Srgrimes{ 1331638Srgrimes long id = htonl(object->object_id); 1341638Srgrimes u_char cryptkey[8]; 1351638Srgrimes u_char newpwd[16]; /* new passwd as stored by server */ 1361638Srgrimes u_char oldpwd[16]; /* old passwd as stored by server */ 1371638Srgrimes u_char len; 1381638Srgrimes DECLARE_RQ; 1391638Srgrimes 1401638Srgrimes memcpy(cryptkey, key, 8); 1411638Srgrimes nw_keyhash((u_char *)&id, oldpasswd, strlen(oldpasswd), oldpwd); 1421638Srgrimes nw_keyhash((u_char *)&id, newpasswd, strlen(newpasswd), newpwd); 1431638Srgrimes nw_encrypt(cryptkey, oldpwd, cryptkey); 1441638Srgrimes nw_passencrypt(oldpwd, newpwd, newpwd); 1451638Srgrimes nw_passencrypt(oldpwd + 8, newpwd + 8, newpwd + 8); 1461638Srgrimes if ((len = strlen(newpasswd)) > 63) { 1471638Srgrimes len = 63; 1481638Srgrimes } 1491638Srgrimes len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40; 1501638Srgrimes 1511638Srgrimes ncp_init_request_s(conn, 75); 1521638Srgrimes ncp_add_mem(conn, cryptkey, 8); 1531638Srgrimes ncp_add_word_hl(conn, object->object_type); 1541638Srgrimes ncp_add_pstring(conn, object->object_name); 1551638Srgrimes ncp_add_byte(conn, len); 1561638Srgrimes ncp_add_mem(conn, newpwd, 16); 1571638Srgrimes return ncp_request(connid, 23, conn); 1581638Srgrimes} 1591638Srgrimes 1601638Srgrimes/* 1611638Srgrimes * target is a 8-byte buffer 1621638Srgrimes */ 1631638Srgrimesint 1641638Srgrimesncp_get_encryption_key(NWCONN_HANDLE cH, char *target) { 1651638Srgrimes int error; 1661638Srgrimes DECLARE_RQ; 1671638Srgrimes 1681638Srgrimes ncp_init_request_s(conn, 23); 1691638Srgrimes 1701638Srgrimes error = ncp_request(cH, 23, conn); 1711638Srgrimes if (error) 1721638Srgrimes return error; 1731638Srgrimes if (conn->rpsize < 8) 1741638Srgrimes return EACCES; 1751638Srgrimes memcpy(target, ncp_reply_data(conn, 0), 8); 1761638Srgrimes return 0; 1771638Srgrimes} 1781638Srgrimes 1791638Srgrimesint 1801638Srgrimesncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd, 1811638Srgrimes struct ncp_bindery_object *objinfo) 1821638Srgrimes{ 1831638Srgrimes u_long id = htonl(objinfo->object_id); 1841638Srgrimes u_char cryptkey[8]; 1851638Srgrimes u_char buf[128]; 1861638Srgrimes DECLARE_RQ; 1871638Srgrimes 1881638Srgrimes nw_keyhash((u_char *)&id, passwd, strlen(passwd), buf); 1891638Srgrimes nw_encrypt(key, buf, cryptkey); 1901638Srgrimes 1911638Srgrimes ncp_init_request_s(conn, 74); 1921638Srgrimes ncp_add_mem(conn, cryptkey, sizeof(cryptkey)); 1931638Srgrimes ncp_add_word_hl(conn, objinfo->object_type); 1941638Srgrimes ncp_add_pstring(conn, objinfo->object_name); 1951638Srgrimes 1961638Srgrimes return ncp_request(cH, 23, conn); 1971638Srgrimes} 1981638Srgrimes 1991638Srgrimesstatic char passkeys[256 + 16] = { 2001638Srgrimes 0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09, 2011638Srgrimes 0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a, 2021638Srgrimes 0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08, 2031638Srgrimes 0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07, 2041638Srgrimes 0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00, 2051638Srgrimes 0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07, 2061638Srgrimes 0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09, 2071638Srgrimes 0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e, 2081638Srgrimes 0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00, 2091638Srgrimes 0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09, 2101638Srgrimes 0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c, 2111638Srgrimes 0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e, 2121638Srgrimes 0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07, 2131638Srgrimes 0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f, 2141638Srgrimes 0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e, 2151638Srgrimes 0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c, 2161638Srgrimes 0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a, 2171638Srgrimes 0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09, 2181638Srgrimes 0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f, 2191638Srgrimes 0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09, 2201638Srgrimes 0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00, 2211638Srgrimes 0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08, 2221638Srgrimes 0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04, 2231638Srgrimes 0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06, 2241638Srgrimes 0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b, 2251638Srgrimes 0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d, 2261638Srgrimes 0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c, 2271638Srgrimes 0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d, 2281638Srgrimes 0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01, 2291638Srgrimes 0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a, 2301638Srgrimes 0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00, 2311638Srgrimes 0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02, 2321638Srgrimes 0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05, 2331638Srgrimes 0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08 2341638Srgrimes}; 23516398Swosch 236static void 237nw_passencrypt(char *old, char *new, char *out) 238{ 239 char *p, v; 240 char copy[8]; 241 int i, di, ax; 242 243#define HIGH(x) (((x) >> 4) & 0xf) 244#define LOW(x) ((x) & 0xf) 245 memcpy(copy, new, 8); 246 247 for (i = 0; i < 16; i++) { 248 for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) { 249 v = copy[di] ^ *p; 250 copy[di] = (passkeys[HIGH(v) + ax + 0x10] << 4) | 251 passkeys[LOW(v) + ax]; 252 } 253 v = old[7]; 254 for (p = old + 7; p > old; p--) { 255 *p = HIGH(p[-1]) | ((*p) << 4); 256 } 257 *old = HIGH(v) | (*old) << 4; 258 bzero(out, 8); 259 260 for (di = 0; di < 16; di++) { 261 v = passkeys[di + 0x100]; 262 v = (v & 1) ? HIGH(copy[v / 2]) : LOW(copy[v / 2]); 263 out[di / 2] |= ((di & 1) ? v << 4 : v); 264 } 265 memcpy(copy, out, 8); 266 } 267} 268