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