1 /*
2  * Copyright (c) 2010, Oracle America, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  *       copyright notice, this list of conditions and the following
12  *       disclaimer in the documentation and/or other materials
13  *       provided with the distribution.
14  *     * Neither the name of the "Oracle America, Inc." nor the names of its
15  *       contributors may be used to endorse or promote products derived
16  *       from this software without specific prior written permission.
17  *
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <rpcsvc/yp.h>
33 #include <rpcsvc/ypclnt.h>
34 #include <shlib-compat.h>
35 
36 /* The NIS v2 protocol suggests 1024 bytes as a maximum length of all fields.
37    Current Linux systems don't use this limit. To remain compatible with
38    recent Linux systems we choose limits large enough to load large key and
39    data values, but small enough to not pose a DoS threat. */
40 
41 #define XDRMAXNAME 1024
42 #define XDRMAXRECORD (16 * 1024 * 1024)
43 
44 bool_t
xdr_ypstat(XDR * xdrs,ypstat * objp)45 xdr_ypstat (XDR *xdrs, ypstat *objp)
46 {
47   return xdr_enum (xdrs, (enum_t *) objp);
48 }
libnsl_hidden_nolink_def(xdr_ypstat,GLIBC_2_0)49 libnsl_hidden_nolink_def (xdr_ypstat, GLIBC_2_0)
50 
51 bool_t
52 xdr_ypxfrstat (XDR *xdrs, ypxfrstat *objp)
53 {
54   return xdr_enum (xdrs, (enum_t *) objp);
55 }
libnsl_hidden_nolink_def(xdr_ypxfrstat,GLIBC_2_0)56 libnsl_hidden_nolink_def (xdr_ypxfrstat, GLIBC_2_0)
57 
58 bool_t
59 xdr_domainname (XDR *xdrs, domainname *objp)
60 {
61   return xdr_string (xdrs, objp, XDRMAXNAME);
62 }
libnsl_hidden_nolink_def(xdr_domainname,GLIBC_2_0)63 libnsl_hidden_nolink_def (xdr_domainname, GLIBC_2_0)
64 
65 bool_t
66 xdr_mapname (XDR *xdrs, mapname *objp)
67 {
68   return xdr_string (xdrs, objp, XDRMAXNAME);
69 }
libnsl_hidden_nolink_def(xdr_mapname,GLIBC_2_0)70 libnsl_hidden_nolink_def (xdr_mapname, GLIBC_2_0)
71 
72 bool_t
73 xdr_peername (XDR *xdrs, peername *objp)
74 {
75   return xdr_string (xdrs, objp, XDRMAXNAME);
76 }
libnsl_hidden_nolink_def(xdr_peername,GLIBC_2_0)77 libnsl_hidden_nolink_def (xdr_peername, GLIBC_2_0)
78 
79 bool_t
80 xdr_keydat (XDR *xdrs, keydat *objp)
81 {
82   return xdr_bytes (xdrs, (char **) &objp->keydat_val,
83 		    (u_int *) &objp->keydat_len, XDRMAXRECORD);
84 }
libnsl_hidden_nolink_def(xdr_keydat,GLIBC_2_0)85 libnsl_hidden_nolink_def (xdr_keydat, GLIBC_2_0)
86 
87 bool_t
88 xdr_valdat (XDR *xdrs, valdat *objp)
89 {
90   return xdr_bytes (xdrs, (char **) &objp->valdat_val,
91 		    (u_int *) &objp->valdat_len, XDRMAXRECORD);
92 }
libnsl_hidden_nolink_def(xdr_valdat,GLIBC_2_0)93 libnsl_hidden_nolink_def (xdr_valdat, GLIBC_2_0)
94 
95 bool_t
96 xdr_ypmap_parms (XDR *xdrs, ypmap_parms *objp)
97 {
98   if (!xdr_domainname (xdrs, &objp->domain))
99     return FALSE;
100   if (!xdr_mapname (xdrs, &objp->map))
101     return FALSE;
102   if (!xdr_u_int (xdrs, &objp->ordernum))
103     return FALSE;
104   return xdr_peername (xdrs, &objp->peer);
105 }
libnsl_hidden_nolink_def(xdr_ypmap_parms,GLIBC_2_0)106 libnsl_hidden_nolink_def (xdr_ypmap_parms, GLIBC_2_0)
107 
108 bool_t
109 xdr_ypreq_key (XDR *xdrs, ypreq_key *objp)
110 {
111   if (!xdr_domainname (xdrs, &objp->domain))
112     return FALSE;
113   if (!xdr_mapname (xdrs, &objp->map))
114     return FALSE;
115   return xdr_keydat (xdrs, &objp->key);
116 }
libnsl_hidden_nolink_def(xdr_ypreq_key,GLIBC_2_0)117 libnsl_hidden_nolink_def (xdr_ypreq_key, GLIBC_2_0)
118 
119 bool_t
120 xdr_ypreq_nokey (XDR *xdrs, ypreq_nokey *objp)
121 {
122   if (!xdr_domainname (xdrs, &objp->domain))
123     return FALSE;
124   return xdr_mapname (xdrs, &objp->map);
125 }
libnsl_hidden_nolink_def(xdr_ypreq_nokey,GLIBC_2_0)126 libnsl_hidden_nolink_def (xdr_ypreq_nokey, GLIBC_2_0)
127 
128 bool_t
129 xdr_ypreq_xfr (XDR *xdrs, ypreq_xfr *objp)
130 {
131   if (!xdr_ypmap_parms (xdrs, &objp->map_parms))
132     return FALSE;
133   if (!xdr_u_int (xdrs, &objp->transid))
134     return FALSE;
135   if (!xdr_u_int (xdrs, &objp->prog))
136     return FALSE;
137   return xdr_u_int (xdrs, &objp->port);
138 }
libnsl_hidden_nolink_def(xdr_ypreq_xfr,GLIBC_2_0)139 libnsl_hidden_nolink_def (xdr_ypreq_xfr, GLIBC_2_0)
140 
141 bool_t
142 xdr_ypresp_val (XDR *xdrs, ypresp_val *objp)
143 {
144   if (!xdr_ypstat (xdrs, &objp->stat))
145     return FALSE;
146   return xdr_valdat (xdrs, &objp->val);
147 }
libnsl_hidden_nolink_def(xdr_ypresp_val,GLIBC_2_0)148 libnsl_hidden_nolink_def (xdr_ypresp_val, GLIBC_2_0)
149 
150 bool_t
151 xdr_ypresp_key_val (XDR *xdrs, ypresp_key_val *objp)
152 {
153   if (!xdr_ypstat (xdrs, &objp->stat))
154     return FALSE;
155   if (!xdr_valdat (xdrs, &objp->val))
156     return FALSE;
157   return xdr_keydat (xdrs, &objp->key);
158 }
libnsl_hidden_nolink_def(xdr_ypresp_key_val,GLIBC_2_0)159 libnsl_hidden_nolink_def (xdr_ypresp_key_val, GLIBC_2_0)
160 
161 bool_t
162 xdr_ypresp_master (XDR *xdrs, ypresp_master *objp)
163 {
164   if (!xdr_ypstat (xdrs, &objp->stat))
165     return FALSE;
166   return xdr_peername (xdrs, &objp->peer);
167 }
libnsl_hidden_nolink_def(xdr_ypresp_master,GLIBC_2_0)168 libnsl_hidden_nolink_def (xdr_ypresp_master, GLIBC_2_0)
169 
170 bool_t
171 xdr_ypresp_order (XDR *xdrs, ypresp_order *objp)
172 {
173   if (!xdr_ypstat (xdrs, &objp->stat))
174     return FALSE;
175   return xdr_u_int (xdrs, &objp->ordernum);
176 }
libnsl_hidden_nolink_def(xdr_ypresp_order,GLIBC_2_0)177 libnsl_hidden_nolink_def (xdr_ypresp_order, GLIBC_2_0)
178 
179 bool_t
180 xdr_ypresp_all (XDR *xdrs, ypresp_all *objp)
181 {
182   if (!xdr_bool (xdrs, &objp->more))
183     return FALSE;
184   switch (objp->more)
185     {
186     case TRUE:
187       return xdr_ypresp_key_val (xdrs, &objp->ypresp_all_u.val);
188     case FALSE:
189       break;
190     default:
191       return FALSE;
192     }
193   return TRUE;
194 }
libnsl_hidden_nolink_def(xdr_ypresp_all,GLIBC_2_0)195 libnsl_hidden_nolink_def (xdr_ypresp_all, GLIBC_2_0)
196 
197 bool_t
198 xdr_ypresp_xfr (XDR *xdrs, ypresp_xfr *objp)
199 {
200   if (!xdr_u_int (xdrs, &objp->transid))
201     return FALSE;
202   return xdr_ypxfrstat (xdrs, &objp->xfrstat);
203 }
libnsl_hidden_nolink_def(xdr_ypresp_xfr,GLIBC_2_0)204 libnsl_hidden_nolink_def (xdr_ypresp_xfr, GLIBC_2_0)
205 
206 bool_t
207 xdr_ypmaplist (XDR *xdrs, ypmaplist *objp)
208 {
209   if (!xdr_mapname (xdrs, &objp->map))
210     return FALSE;
211   /* Prevent gcc warning about alias violation.  */
212   char **tp = (void *) &objp->next;
213   return xdr_pointer (xdrs, tp, sizeof (ypmaplist), (xdrproc_t) xdr_ypmaplist);
214 }
libnsl_hidden_nolink_def(xdr_ypmaplist,GLIBC_2_0)215 libnsl_hidden_nolink_def (xdr_ypmaplist, GLIBC_2_0)
216 
217 bool_t
218 xdr_ypresp_maplist (XDR *xdrs, ypresp_maplist *objp)
219 {
220   if (!xdr_ypstat (xdrs, &objp->stat))
221     return FALSE;
222   /* Prevent gcc warning about alias violation.  */
223   char **tp = (void *) &objp->maps;
224   return xdr_pointer (xdrs, tp, sizeof (ypmaplist), (xdrproc_t) xdr_ypmaplist);
225 }
libnsl_hidden_nolink_def(xdr_ypresp_maplist,GLIBC_2_0)226 libnsl_hidden_nolink_def (xdr_ypresp_maplist, GLIBC_2_0)
227 
228 bool_t
229 xdr_yppush_status (XDR *xdrs, yppush_status *objp)
230 {
231   return xdr_enum (xdrs, (enum_t *) objp);
232 }
libnsl_hidden_nolink_def(xdr_yppush_status,GLIBC_2_0)233 libnsl_hidden_nolink_def (xdr_yppush_status, GLIBC_2_0)
234 
235 bool_t
236 xdr_yppushresp_xfr (XDR *xdrs, yppushresp_xfr *objp)
237 {
238   if (!xdr_u_int (xdrs, &objp->transid))
239     return FALSE;
240   return xdr_yppush_status (xdrs, &objp->status);
241 }
libnsl_hidden_nolink_def(xdr_yppushresp_xfr,GLIBC_2_0)242 libnsl_hidden_nolink_def (xdr_yppushresp_xfr, GLIBC_2_0)
243 
244 bool_t
245 xdr_ypbind_resptype (XDR *xdrs, ypbind_resptype *objp)
246 {
247   return xdr_enum (xdrs, (enum_t *) objp);
248 }
libnsl_hidden_nolink_def(xdr_ypbind_resptype,GLIBC_2_0)249 libnsl_hidden_nolink_def (xdr_ypbind_resptype, GLIBC_2_0)
250 
251 bool_t
252 xdr_ypbind_binding (XDR *xdrs, ypbind_binding *objp)
253 {
254   if (!xdr_opaque (xdrs, objp->ypbind_binding_addr, 4))
255     return FALSE;
256   return xdr_opaque (xdrs, objp->ypbind_binding_port, 2);
257 }
libnsl_hidden_nolink_def(xdr_ypbind_binding,GLIBC_2_0)258 libnsl_hidden_nolink_def (xdr_ypbind_binding, GLIBC_2_0)
259 
260 bool_t
261 xdr_ypbind_resp (XDR *xdrs, ypbind_resp *objp)
262 {
263   if (!xdr_ypbind_resptype (xdrs, &objp->ypbind_status))
264     return FALSE;
265   switch (objp->ypbind_status)
266     {
267     case YPBIND_FAIL_VAL:
268       return xdr_u_int (xdrs, &objp->ypbind_resp_u.ypbind_error);
269     case YPBIND_SUCC_VAL:
270       return xdr_ypbind_binding (xdrs, &objp->ypbind_resp_u.ypbind_bindinfo);
271     }
272   return FALSE;
273 }
libnsl_hidden_nolink_def(xdr_ypbind_resp,GLIBC_2_0)274 libnsl_hidden_nolink_def (xdr_ypbind_resp, GLIBC_2_0)
275 
276 bool_t
277 xdr_ypbind_setdom (XDR *xdrs, ypbind_setdom *objp)
278 {
279   if (!xdr_domainname (xdrs, &objp->ypsetdom_domain))
280     return FALSE;
281   if (!xdr_ypbind_binding (xdrs, &objp->ypsetdom_binding))
282     return FALSE;
283   return xdr_u_int (xdrs, &objp->ypsetdom_vers);
284 }
libnsl_hidden_nolink_def(xdr_ypbind_setdom,GLIBC_2_0)285 libnsl_hidden_nolink_def (xdr_ypbind_setdom, GLIBC_2_0)
286 
287 bool_t
288 xdr_ypall(XDR *xdrs, struct ypall_callback *incallback)
289 {
290     struct ypresp_key_val out;
291     char key[YPMAXRECORD], val[YPMAXRECORD];
292 
293     /*
294      * Set up key/val struct to be used during the transaction.
295      */
296     memset(&out, 0, sizeof out);
297     out.key.keydat_val = key;
298     out.key.keydat_len = sizeof(key);
299     out.val.valdat_val = val;
300     out.val.valdat_len = sizeof(val);
301 
302     for (;;) {
303 	bool_t more, status;
304 
305 	/* Values pending? */
306 	if (!xdr_bool(xdrs, &more))
307 	    return FALSE;           /* can't tell! */
308 	if (!more)
309 	    return TRUE;            /* no more */
310 
311 	/* Transfer key/value pair. */
312 	status = xdr_ypresp_key_val(xdrs, &out);
313 
314 	/*
315 	 * If we succeeded, call the callback function.
316 	 * The callback will return TRUE when it wants
317 	 * no more values.  If we fail, indicate the
318 	 * error.
319 	 */
320 	if (status) {
321 	    if ((*incallback->foreach)(out.stat,
322 				       (char *)out.key.keydat_val, out.key.keydat_len,
323 				       (char *)out.val.valdat_val, out.val.valdat_len,
324 				       incallback->data))
325 		return TRUE;
326 	} else
327 	    return FALSE;
328     }
329 }
330 libnsl_hidden_nolink_def (xdr_ypall, GLIBC_2_2)
331