1 /* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */ 2 /* 3 * Copyright (c) 2010, Oracle America, Inc. 4 * 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * * Neither the name of the "Oracle America, Inc." nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 #if !defined(lint) && defined(SCCSIDS) 35 static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; 36 #endif 37 38 /* 39 * rpc_prot.c 40 * 41 * This set of routines implements the rpc message definition, 42 * its serializer and some common rpc utility routines. 43 * The routines are meant for various implementations of rpc - 44 * they are NOT for the rpc client or rpc service implementations! 45 * Because authentication stuff is easy and is part of rpc, the opaque 46 * routines are also in this program. 47 */ 48 49 #include <sys/param.h> 50 51 #include <gssrpc/rpc.h> 52 53 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ 54 55 /* 56 * XDR an opaque authentication struct 57 * (see auth.h) 58 */ 59 bool_t 60 xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap) 61 { 62 63 if (xdr_enum(xdrs, &(ap->oa_flavor))) 64 return (xdr_bytes(xdrs, &ap->oa_base, 65 &ap->oa_length, MAX_AUTH_BYTES)); 66 return (FALSE); 67 } 68 69 /* 70 * XDR a DES block 71 */ 72 bool_t 73 xdr_des_block(XDR *xdrs, des_block *blkp) 74 { 75 return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); 76 } 77 78 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ 79 80 /* 81 * XDR the MSG_ACCEPTED part of a reply message union 82 */ 83 bool_t 84 xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar) 85 { 86 87 /* personalized union, rather than calling xdr_union */ 88 if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) 89 return (FALSE); 90 if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) 91 return (FALSE); 92 switch (ar->ar_stat) { 93 94 case SUCCESS: 95 return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); 96 97 case PROG_MISMATCH: 98 if (! xdr_rpcvers(xdrs, &(ar->ar_vers.low))) 99 return (FALSE); 100 return (xdr_rpcvers(xdrs, &(ar->ar_vers.high))); 101 102 case GARBAGE_ARGS: 103 case SYSTEM_ERR: 104 case PROC_UNAVAIL: 105 case PROG_UNAVAIL: 106 break; 107 } 108 return (TRUE); /* TRUE => open ended set of problems */ 109 } 110 111 /* 112 * XDR the MSG_DENIED part of a reply message union 113 */ 114 bool_t 115 xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr) 116 { 117 118 /* personalized union, rather than calling xdr_union */ 119 if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) 120 return (FALSE); 121 switch (rr->rj_stat) { 122 123 case RPC_MISMATCH: 124 if (! xdr_rpcvers(xdrs, &(rr->rj_vers.low))) 125 return (FALSE); 126 return (xdr_rpcvers(xdrs, &(rr->rj_vers.high))); 127 128 case AUTH_ERROR: 129 return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); 130 } 131 return (FALSE); 132 } 133 134 static struct xdr_discrim reply_dscrm[3] = { 135 { (int)MSG_ACCEPTED, xdr_accepted_reply }, 136 { (int)MSG_DENIED, xdr_rejected_reply }, 137 { __dontcare__, NULL_xdrproc_t } }; 138 139 /* 140 * XDR a reply message 141 */ 142 bool_t 143 xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg) 144 { 145 if ( 146 xdr_u_int32(xdrs, &(rmsg->rm_xid)) && 147 xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && 148 (rmsg->rm_direction == REPLY) ) 149 return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), 150 (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); 151 return (FALSE); 152 } 153 154 155 /* 156 * Serializes the "static part" of a call message header. 157 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. 158 * The rm_xid is not really static, but the user can easily munge on the fly. 159 */ 160 bool_t 161 xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg) 162 { 163 164 cmsg->rm_direction = CALL; 165 cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; 166 if ( 167 (xdrs->x_op == XDR_ENCODE) && 168 xdr_u_int32(xdrs, &(cmsg->rm_xid)) && 169 xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && 170 xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_rpcvers)) && 171 xdr_rpcprog(xdrs, &(cmsg->rm_call.cb_prog)) ) 172 return (xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_vers))); 173 return (FALSE); 174 } 175 176 /* ************************** Client utility routine ************* */ 177 178 static void 179 accepted(enum accept_stat acpt_stat, struct rpc_err *error) 180 { 181 182 switch (acpt_stat) { 183 184 case PROG_UNAVAIL: 185 error->re_status = RPC_PROGUNAVAIL; 186 return; 187 188 case PROG_MISMATCH: 189 error->re_status = RPC_PROGVERSMISMATCH; 190 return; 191 192 case PROC_UNAVAIL: 193 error->re_status = RPC_PROCUNAVAIL; 194 return; 195 196 case GARBAGE_ARGS: 197 error->re_status = RPC_CANTDECODEARGS; 198 return; 199 200 case SYSTEM_ERR: 201 error->re_status = RPC_SYSTEMERROR; 202 return; 203 204 case SUCCESS: 205 error->re_status = RPC_SUCCESS; 206 return; 207 } 208 /* something's wrong, but we don't know what ... */ 209 error->re_status = RPC_FAILED; 210 error->re_lb.s1 = (int32_t)MSG_ACCEPTED; 211 error->re_lb.s2 = (int32_t)acpt_stat; 212 } 213 214 static void 215 rejected(enum reject_stat rjct_stat, struct rpc_err *error) 216 { 217 218 switch (rjct_stat) { 219 220 case RPC_MISMATCH: 221 error->re_status = RPC_VERSMISMATCH; 222 return; 223 224 case AUTH_ERROR: 225 error->re_status = RPC_AUTHERROR; 226 return; 227 } 228 /* something's wrong, but we don't know what ... */ 229 error->re_status = RPC_FAILED; 230 error->re_lb.s1 = (int32_t)MSG_DENIED; 231 error->re_lb.s2 = (int32_t)rjct_stat; 232 } 233 234 /* 235 * given a reply message, fills in the error 236 */ 237 void 238 gssrpc__seterr_reply(struct rpc_msg *msg, struct rpc_err *error) 239 { 240 241 /* optimized for normal, SUCCESSful case */ 242 switch (msg->rm_reply.rp_stat) { 243 244 case MSG_ACCEPTED: 245 if (msg->acpted_rply.ar_stat == SUCCESS) { 246 error->re_status = RPC_SUCCESS; 247 return; 248 }; 249 accepted(msg->acpted_rply.ar_stat, error); 250 break; 251 252 case MSG_DENIED: 253 rejected(msg->rjcted_rply.rj_stat, error); 254 break; 255 256 default: 257 error->re_status = RPC_FAILED; 258 error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat); 259 break; 260 } 261 switch (error->re_status) { 262 263 case RPC_VERSMISMATCH: 264 error->re_vers.low = msg->rjcted_rply.rj_vers.low; 265 error->re_vers.high = msg->rjcted_rply.rj_vers.high; 266 break; 267 268 case RPC_AUTHERROR: 269 error->re_why = msg->rjcted_rply.rj_why; 270 break; 271 272 case RPC_PROGVERSMISMATCH: 273 error->re_vers.low = msg->acpted_rply.ar_vers.low; 274 error->re_vers.high = msg->acpted_rply.ar_vers.high; 275 break; 276 277 case RPC_FAILED: 278 case RPC_SUCCESS: 279 case RPC_PROGNOTREGISTERED: 280 case RPC_PMAPFAILURE: 281 case RPC_UNKNOWNPROTO: 282 case RPC_UNKNOWNHOST: 283 case RPC_SYSTEMERROR: 284 case RPC_CANTDECODEARGS: 285 case RPC_PROCUNAVAIL: 286 case RPC_PROGUNAVAIL: 287 case RPC_TIMEDOUT: 288 case RPC_CANTRECV: 289 case RPC_CANTSEND: 290 case RPC_CANTDECODERES: 291 case RPC_CANTENCODEARGS: 292 default: 293 break; 294 } 295 } 296