]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/lib/libncp/ncpl_bind.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / 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
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/types.h>
37 #include <arpa/inet.h>
38 #include <errno.h>
39 #include <string.h>
40 #include <netncp/ncp_lib.h>
41
42 static void nw_passencrypt(char *old, char *new, char *out);
43
44 int
45 ncp_get_bindery_object_id(NWCONN_HANDLE connid, u_int16_t object_type,
46         const char *object_name, struct ncp_bindery_object *target)
47 {
48         int error;
49         DECLARE_RQ;
50
51         ncp_init_request_s(conn, 53);
52         ncp_add_word_hl(conn, object_type);
53         ncp_add_pstring(conn, object_name);
54
55         if ((error = ncp_request(connid, 23, conn)) != 0) {
56                 return error;
57         }
58         if (conn->rpsize < 54) {
59                 return EACCES;
60         }
61         target->object_id = ncp_reply_dword_hl(conn, 0);
62         target->object_type = ncp_reply_word_hl(conn, 4);
63         memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
64         return 0;
65 }
66
67 int
68 ncp_read_property_value(NWCONN_HANDLE connid, int object_type,
69         const char *object_name, int segment, const char *prop_name,
70         struct nw_property *target)
71 {
72         int error;
73         struct ncp_buf conn;
74         ncp_init_request_s(&conn, 61);
75         ncp_add_word_hl(&conn, object_type);
76         ncp_add_pstring(&conn, object_name);
77         ncp_add_byte(&conn, segment);
78         ncp_add_pstring(&conn, prop_name);
79
80         if ((error = ncp_request(connid,23,&conn)) != 0) {
81                 return error;
82         }
83         memcpy(&(target->value), ncp_reply_data(&conn, 0), 128);
84         target->more_flag = ncp_reply_byte(&conn, 128);
85         target->property_flag = ncp_reply_byte(&conn, 129);
86         return 0;
87 }
88
89 int
90 ncp_scan_bindery_object(NWCONN_HANDLE connid, u_int32_t last_id,
91         u_int16_t object_type, char *search_string,
92         struct ncp_bindery_object *target)
93 {
94         int error;
95         DECLARE_RQ;
96
97         ncp_init_request_s(conn, 55);
98         ncp_add_dword_hl(conn, last_id);
99         ncp_add_word_hl(conn, object_type);
100         ncp_add_pstring(conn, search_string);
101         error = ncp_request(connid, 23, conn);
102         if (error) return error;
103         target->object_id = ncp_reply_dword_hl(conn, 0);
104         target->object_type = ncp_reply_word_hl(conn, 4);
105         memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN);
106         target->object_flags = ncp_reply_byte(conn, 54);
107         target->object_security = ncp_reply_byte(conn, 55);
108         target->object_has_prop = ncp_reply_byte(conn, 56);
109         return 0;
110 }
111
112 int
113 ncp_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
129 int
130 ncp_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  */
166 int
167 ncp_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
182 int
183 ncp_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
202 static 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
239 static void
240 nw_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 }