/* * Simple memory allocator, allocates aligned physical memory. * Note that startup_kernel() only allocates memory, never frees. * Memory usage just grows in an upward direction. */ static void * do_mem_alloc(uint32_t size, uint32_t align) { uint_t i; uint64_t best; uint64_t start; uint64_t end; /* * make sure size is a multiple of pagesize */ size = RNDUP(size, MMU_PAGESIZE); next_avail_addr = RNDUP(next_avail_addr, align); /* * XXPV fixme joe * * a really large bootarchive that causes you to run out of memory * may cause this to blow up */ /* LINTED E_UNEXPECTED_UINT_PROMOTION */ best = (uint64_t)-size; for (i = 0; i < memlists_used; ++i) { start = memlists[i].addr; #if defined(__xpv) start += mfn_base; #endif end = start + memlists[i].size; /* * did we find the desired address? */ if (start <= next_avail_addr && next_avail_addr + size <= end) { best = next_avail_addr; goto done; } /* * if not is this address the best so far? */ if (start > next_avail_addr && start < best && RNDUP(start, align) + size <= end) best = RNDUP(start, align); } /* * We didn't find exactly the address we wanted, due to going off the * end of a memory region. Return the best found memory address. */ done: next_avail_addr = best + size; #if defined(__xpv) if (next_avail_addr > scratch_end) dboot_panic("Out of mem next_avail: 0x%lx, scratch_end: " "0x%lx", (ulong_t)next_avail_addr, (ulong_t)scratch_end); #endif (void) memset((void *)(uintptr_t)best, 0, size); return ((void *)(uintptr_t)best); }
PPLLIST PLListListImport(PPLLIST pList, PPLLIST pImport, HNDPLLITEM hNode) { PPLLNODE pParent, pi; ULONG cb; INT i; char buffer[256]; // only for TRACE messages if ( !pList ) return NULL; // allocation needed for the current item cb = pImport->cbTot - sizeof(PLLIST); // if the current allocation size is not enough reallocate the list sprintf (buffer, "total (pList->cbTot): %ld, new item: %ld, pImport->cbTot: %ld sizeof(PLLIST): %ld", pList->cbTot, cb, pImport->cbTot, sizeof(PLLIST)); TRACE1("%s", buffer); sprintf (buffer, "try to reallocate %ld (0x%X),cb: %ld", RNDUP(pList->cbTot + cb, pList->cbGrow), RNDUP(pList->cbTot + cb, pList->cbGrow), cb ); TRACE1("%s", buffer); TRACE2("sizeof(pList) %d (0x%X)", sizeof(pList), sizeof(pList)); TRACE2("pointer to pList before realloc: 0x%X, pImport: 0x%X", pList, pImport); if ( (RNDUP(pList->cbTot, pList->cbGrow) >= (pList->cbTot + cb)) || (NULL != (pList = realloc(pList, RNDUP(pList->cbTot + cb, pList->cbGrow)))) ) { TRACE1("pList after realloc 0x%X", pList); pi = (PPLLNODE)((PBYTE)pList + pList->cbTot); // get the address of the parent node pParent = PNODEFROMHITEM(pList, hNode); TRACE1("pParent 0x%X", pParent); PREVITEM(pList, pParent)->offNext = pList->cbTot; pParent->offLast = pList->cbTot; // copy the data from the previous list to the current list memcpy(pi, (PBYTE)pImport + sizeof(PLLIST), cb); // update the offsets pParent->count += pImport->count; TRACE1("pParent->count %ld", pParent->count); for ( i = 0, cb = pList->cbTot - sizeof(PLLIST); i < pImport->count; ++i ) { if ( pi->offNext ) { pi->offNext += cb; } else { pParent->offLast = (HNDPLLITEM)((PBYTE)pi - (PBYTE)pList); } /* endif */ // if the current item is a node if ( pi->isNode ) { updateImpListOffsets((PPLLIST)((PBYTE)pList + cb), pi, cb); pi->offFirst += cb; pi->offLast += cb; pi->offParent = hNode; } /* endif */ pi = (PPLLNODE)NEXTITEM(pList, pi); } /* endfor */ pList->cbTot += pImport->cbTot - sizeof(PLLIST); TRACE1("pList->cbTot %ld", pList->cbTot); } /* endif */ TRACE1("pList after realloc 0x%X", pList); return pList; }
static bool_t svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[128]; int32_t *buf; log_debug("in svcauth_gss_validate()"); memset(rpchdr, 0, sizeof(rpchdr)); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); /* 8 XDR units from the IXDR macro calls. */ if (sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))) return (FALSE); buf = (int32_t *)(void *)rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { memcpy((caddr_t)buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *)buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_verify_mic", maj_stat, min_stat); if (log_badverf != NULL) (*log_badverf)(gd->client_name, svcauth_gss_name, rqst, msg, log_badverf_data); return (FALSE); } return (TRUE); }
PPLLIST PLListExport(PPLLIST pList, HNDPLLITEM hNode, BOOL inclNode, ULONG cbGrow) { PPLLIST pnew, p; ULONG cbTot; PPLLNODE pnode, pn; // check the cbGrow parameter if ( !cbGrow ) cbGrow = pList->cbGrow; // if hNode is 0 just duplicate the list if ( !hNode ) { if ( NULL != (pnew = malloc(RNDUP(pList->cbTot, cbGrow))) ) { memcpy(pnew, pList, pList->cbTot); pnew->cbGrow = cbGrow; } /* endif */ pnew; } /* endif */ // calculate the size of the allocation needed for the new list cbTot = sizeof(PLLIST); pnode = PNODEFROMHITEM(pList, hNode); // size of the current node (if requested) if ( inclNode ) cbTot += pnode->offFirst - hNode; // total size of the node content for ( pn = pnode; !pn->offNext; pn = PNODEFROMHITEM(pList, pn->offParent) ) ; cbTot += pn->offNext - pnode->offFirst; // allocate the new list if ( NULL != (pnew = malloc(RNDUP(cbTot, cbGrow))) ) { pnew->cbTot = cbTot; pnew->offFirst = sizeof(PLLIST); pnew->offParent = 0; pnew->cbGrow = cbGrow; if ( inclNode ) { memcpy((PBYTE)pnew + sizeof(PLLIST), pnode, cbTot - sizeof(PLLIST)); pnew->count = 1; pnew->offLast = pnew->offFirst; updateExpListOffsets(pnew, (PPLLNODE)pnew, hNode - sizeof(PLLIST)); } else { memcpy((PBYTE)pnew + sizeof(PLLIST), FIRSTITEM(pList, pnode), cbTot - sizeof(PLLIST)); pnew->count = pnode->count; pnew->offLast = pnode->offLast - pnode->offFirst + sizeof(PLLIST); updateExpListOffsets(pnew, (PPLLNODE)pnew, pnode->offFirst - sizeof(PLLIST)); } /* endif */ } /* endif */ return pnew; }
static u_int fix_buf_size(u_int s) { if (s < 100) s = 4000; return (RNDUP(s)); }
static bool_t xdrmblk_control(XDR *xdrs, int request, void *info) { mblk_t *m; int32_t *int32p; int len; switch (request) { case XDR_PEEK: /* * Return the next 4 byte unit in the XDR stream. */ if (xdrs->x_handy < sizeof (int32_t)) return (FALSE); /* LINTED pointer alignment */ m = (mblk_t *)xdrs->x_base; if (m == NULL) return (FALSE); /* * If the pointer is not aligned, fail the peek */ if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t))) return (FALSE); int32p = (int32_t *)info; /* LINTED pointer alignment */ *int32p = ntohl(*((int32_t *)(m->b_rptr))); return (TRUE); case XDR_SKIPBYTES: /* LINTED pointer alignment */ m = (mblk_t *)xdrs->x_base; if (m == NULL) return (FALSE); int32p = (int32_t *)info; len = RNDUP((int)(*int32p)); if (len < 0) return (FALSE); while ((xdrs->x_handy -= len) < 0) { if ((xdrs->x_handy += len) > 0) { m->b_rptr += xdrs->x_handy; len -= xdrs->x_handy; } m = m->b_cont; xdrs->x_base = (caddr_t)m; if (m == NULL) { xdrs->x_handy = 0; return (FALSE); } xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); } m->b_rptr += len; return (TRUE); default: return (FALSE); } }
/* * During memory allocation, find the highest address not used yet. */ static void check_higher(paddr_t a) { if (a < next_avail_addr) return; next_avail_addr = RNDUP(a + 1, MMU_PAGESIZE); DBG(next_avail_addr); }
static unsigned fix_buf_size( register unsigned s) { if (s < 100) s = 4000; return (RNDUP(s)); }
static void* heapIncrease(Heap_t uhp, size_t* plen, int* pfl) { PVOID p = NULL; *plen = (size_t)RNDUP(*plen, CB_HEAPBLOCK); *pfl = !_BLOCK_CLEAN; logwrite("increaseHeap - size : %8u\n", *plen, 0); if ( DosSubAllocMem(pbasemem, &p, *plen) ) return NULL; return p; }
PPLLIST PLListDup(PPLLIST pList, ULONG cb) { PPLLIST plist; if ( pList && !cb ) cb = RNDUP(pList->cbTot, pList->cbGrow); TRACE1("allocate %d bytes", cb); if ( NULL != (plist = malloc(cb)) ) { if ( pList ) memcpy(plist, pList, pList->cbTot); } /* endif */ return plist; }
/* * System (Unix) longhand authenticator */ enum auth_stat __svcauth_sys(struct svc_req *rqst, struct rpc_msg *msg) { struct authsys_parms *aup; int32_t *buf; struct authsys_area *area; uint_t auth_len; uint_t str_len, gid_len; int i; /* LINTED pointer cast */ area = (struct authsys_area *)rqst->rq_clntcred; aup = &area->area_aup; aup->aup_machname = area->area_machname; aup->aup_gids = area->area_gids; auth_len = msg->rm_call.cb_cred.oa_length; if (auth_len == 0) return (AUTH_BADCRED); /* LINTED pointer cast */ buf = (int32_t *)msg->rm_call.cb_cred.oa_base; aup->aup_time = IXDR_GET_INT32(buf); str_len = IXDR_GET_U_INT32(buf); if (str_len > MAX_MACHINE_NAME) return (AUTH_BADCRED); (void) memcpy(aup->aup_machname, buf, str_len); aup->aup_machname[str_len] = 0; str_len = RNDUP(str_len); buf += str_len / (int)sizeof (int32_t); aup->aup_uid = IXDR_GET_INT32(buf); aup->aup_gid = IXDR_GET_INT32(buf); gid_len = IXDR_GET_U_INT32(buf); if (gid_len > NGRPS) return (AUTH_BADCRED); aup->aup_len = gid_len; for (i = 0; i < gid_len; i++) { aup->aup_gids[i] = (gid_t)IXDR_GET_INT32(buf); } /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) return (AUTH_BADCRED); rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; rqst->rq_xprt->xp_verf.oa_length = 0; return (AUTH_OK); }
PPLLIST PLListNodeAdd(PPLLIST pList, HNDPLLITEM hNode, PHNDPLLITEM pNode, PPLLISTADDITEM pFunc, PVOID pParm) { PPLLNODE pParent, pi; ULONG cbItem; size_t stSize; char buffer[128]; if ( !pList || !pFunc ) return NULL; // allocation needed for the current item cbItem = pFunc(NULL, pParm) + sizeof(PLLNODE); // if the current allocation size is not enough reallocate the list stSize = RNDUP(pList->cbTot + cbItem, pList->cbGrow); sprintf (buffer, "new size to allocate %ld, total: %ld, item: %ld", stSize, pList->cbTot, cbItem); TRACE1("%s", buffer); if ( (RNDUP(pList->cbTot, pList->cbGrow) >= (pList->cbTot + cbItem)) || (NULL != (pList = realloc(pList, stSize ))) ) { TRACE1("pList after realloc: 0x%X", pList); pi = (PPLLNODE)((PBYTE)pList + pList->cbTot); if ( pNode ) *pNode = pList->cbTot; // get the address of the parent node pParent = PNODEFROMHITEM(pList, hNode); PREVITEM(pList, pParent)->offNext = pList->cbTot; pParent->offLast = pList->cbTot; pi->offFirst = (pList->cbTot += cbItem); pi->offNext = 0; pi->isNode = 1; pi->offLast = 0; pi->offParent = (ULONG)hNode; pi->count = 0; // set the item data via the callback procedure pFunc(pi + 1, pParm); pParent->count++; // update the items count } /* endif */ return pList; }
PPLLIST PLListItemAdd(PPLLIST pList, HNDPLLITEM hNode, PHNDPLLITEM phItem, PPLLISTADDITEM pFunc, PVOID pParm) { PPLLNODE pParent; ULONG cbItem; PPLLITEM pi; if ( !pList || !pFunc ) return NULL; // allocation needed for the current item cbItem = pFunc(NULL, pParm) + sizeof(PLLITEM); // if the current allocation size is not enough reallocate the list if ( RNDUP(pList->cbTot, pList->cbGrow) < RNDUP(pList->cbTot + cbItem, pList->cbGrow) ) { TRACE("reallocating"); TRACE2("pList->cbTot: %ld, cbItem: %ld", pList->cbTot, cbItem); pList = realloc(pList, RNDUP(pList->cbTot + cbItem, pList->cbGrow)); TRACE("reallocating OKAY"); } if ( pList ) { pi = (PPLLITEM)((PBYTE)pList + pList->cbTot); if ( phItem ) *phItem = pList->cbTot; // get the address of the parent node pParent = PNODEFROMHITEM(pList, hNode); PREVITEM(pList, pParent)->offNext = pList->cbTot; pParent->offLast = pList->cbTot; pList->cbTot += cbItem; pi->offNext = 0; pi->isNode = 0; // set the other item data via the callback procedure pFunc(pi + 1, pParm); pParent->count++; // update the items count } /* endif */ if ( pList == NULL ) { TRACE("ERROR: reallocate"); } return pList; }
static int svcauth_gss_validate(struct svc_req *req, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[RPCHDR_LEN]; int32_t *buf; memset(rpchdr, 0, RPCHDR_LEN); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; if (oa->oa_length > MAX_AUTH_BYTES) return GSS_S_CALL_BAD_STRUCTURE; /* XXX since MAX_AUTH_BYTES is 400, the following code trivially * overruns (up to 431 per Coverity, but compare RPCHDR_LEN with * what is marshalled below). */ buf = (int32_t *) rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *) buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: %d %d", __func__, maj_stat, min_stat); return (maj_stat); } return GSS_S_COMPLETE; }
PPLLIST PLListNew(ULONG cbGrow) { PPLLIST pList; if ( !cbGrow ) cbGrow = SLPL_DEFCBGROW; if ( NULL != (pList = malloc(RNDUP(sizeof(PLLIST), cbGrow))) ) { pList->isNode = 1; pList->offLast = pList->cbTot = pList->offFirst = sizeof(PLLIST); pList->offParent = pList->count = 0; pList->cbGrow = cbGrow; TRACE4("addr=0x%X, size requested=%d, actual size=%d, pList->count=%d", pList, cbGrow, RNDUP(sizeof(PLLIST), cbGrow), pList->count ); return pList; } /* endif */ return NULL; }
bool_t xdr_fastfhandle(XDR *xdrs, fhandle_t **fh) { int32_t *ptr; if (xdrs->x_op != XDR_DECODE) return (FALSE); ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t))); if (ptr != NULL) { *fh = (fhandle_t *)ptr; return (TRUE); } return (FALSE); }
static bool_t xdrmem_control(XDR *xdrs, int request, void *info) { xdr_bytesrec *xptr; int32_t *l; int len; switch (request) { case XDR_GET_BYTES_AVAIL: xptr = (xdr_bytesrec *)info; xptr->xc_is_last_record = TRUE; xptr->xc_num_avail = xdrs->x_handy; return (TRUE); case XDR_PEEK: /* * Return the next 4 byte unit in the XDR stream. */ if (xdrs->x_handy < sizeof (int32_t)) return (FALSE); l = (int32_t *)info; *l = (int32_t)ntohl((uint32_t) (*((int32_t *)(xdrs->x_private)))); return (TRUE); case XDR_SKIPBYTES: /* * Skip the next N bytes in the XDR stream. */ l = (int32_t *)info; len = RNDUP((int)(*l)); if (xdrs->x_handy < len) return (FALSE); xdrs->x_handy -= len; xdrs->x_private = (char *)xdrs->x_private + len; return (TRUE); } return (FALSE); }
uint_t calc_length(uint_t len) { len = RNDUP(len); if (len <= 64 * 1024) { if (len > 32 * 1024) { len = 64 * 1024; } else { if (len > 16 * 1024) { len = 32 * 1024; } else { if (len > 8 * 1024) { len = 16 * 1024; } else { len = 8 * 1024; } } } } return (len); }
/* * File access handle * The fhandle struct is treated a opaque data on the wire */ bool_t xdr_fhandle(XDR *xdrs, fhandle_t *fh) { int32_t *ptr; int32_t *fhp; if (xdrs->x_op == XDR_FREE) return (TRUE); ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t))); if (ptr != NULL) { fhp = (int32_t *)fh; if (xdrs->x_op == XDR_DECODE) { *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp = *ptr; } else { *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr = *fhp; } return (TRUE); } return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE)); }
/* * XDR a call message */ bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) { rpc_inline_t *buf; struct opaque_auth *oa; if (xdrs->x_op == XDR_ENCODE) { if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) return (FALSE); if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) return (FALSE); buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_cred.oa_length) + 2 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_verf.oa_length)); if (buf != NULL) { IXDR_PUT_INT32(buf, cmsg->rm_xid); IXDR_PUT_ENUM(buf, cmsg->rm_direction); if (cmsg->rm_direction != CALL) return (FALSE); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) return (FALSE); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_INT32(buf, oa->oa_length); if (oa->oa_length) { (void) memcpy(buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof (int32_t); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_INT32(buf, oa->oa_length); if (oa->oa_length) { (void) memcpy(buf, oa->oa_base, oa->oa_length); /* * no real need.... * buf += RNDUP(oa->oa_length) / sizeof * (int32_t); */ } return (TRUE); } } if (xdrs->x_op == XDR_DECODE) { buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); if (buf != NULL) { cmsg->rm_xid = IXDR_GET_INT32(buf); cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); if (cmsg->rm_direction != CALL) return (FALSE); cmsg->rm_call.cb_rpcvers = IXDR_GET_INT32(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) return (FALSE); cmsg->rm_call.cb_prog = IXDR_GET_INT32(buf); cmsg->rm_call.cb_vers = IXDR_GET_INT32(buf); cmsg->rm_call.cb_proc = IXDR_GET_INT32(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_INT32(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); if (oa->oa_base == NULL) { oa->oa_base = malloc(oa->oa_length); if (oa->oa_base == NULL) { syslog(LOG_ERR, "xdr_callmsg : " "out of memory."); return (FALSE); } } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) return (FALSE); } else { (void) memcpy(oa->oa_base, buf, (size_t)oa->oa_length); /* * no real need.... * buf += RNDUP(oa->oa_length) / * (int)sizeof (int32_t); */ } } oa = &cmsg->rm_call.cb_verf; buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || xdr_u_int(xdrs, &oa->oa_length) == FALSE) return (FALSE); } else { oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_INT32(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) return (FALSE); if (oa->oa_base == NULL) { oa->oa_base = malloc(oa->oa_length); if (oa->oa_base == NULL) { syslog(LOG_ERR, "xdr_callmsg : " "out of memory."); return (FALSE); } } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) return (FALSE); } else { (void) memcpy(oa->oa_base, buf, (size_t)oa->oa_length); /* * no real need... * buf += RNDUP(oa->oa_length) / * (int)sizeof (int32_t); */ } } return (TRUE); }
/* * XDR a call message */ bool_t xdr_callmsg( register XDR *xdrs, register struct rpc_msg *cmsg) { register uint32_t *buf; register struct opaque_auth *oa; if (xdrs->x_op == XDR_ENCODE) { if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { return (FALSE); } buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_cred.oa_length) + 2 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_verf.oa_length)); if (buf != NULL) { IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_xid); IXDR_PUT_ENUM(buf, (uint32_t)cmsg->rm_direction); if (cmsg->rm_direction != CALL) { return (FALSE); } IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_prog); IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_vers); IXDR_PUT_LONG(buf, (uint32_t)cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (char*)buf, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof (*buf); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (char*)buf, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } return (TRUE); } } if (xdrs->x_op == XDR_DECODE) { buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); if (buf != NULL) { cmsg->rm_xid = IXDR_GET_LONG(buf); cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); if (cmsg->rm_direction != CALL) { return (FALSE); } cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf); cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf); cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_LONG(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (char*) mem_alloc(oa->oa_length); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { bcopy((char*)buf, oa->oa_base, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } } oa = &cmsg->rm_call.cb_verf; buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || xdr_u_int(xdrs, &oa->oa_length) == FALSE) { return (FALSE); } } else { oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_LONG(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (char*) mem_alloc(oa->oa_length); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { bcopy((char*)buf, oa->oa_base, oa->oa_length); /* no real need... buf += RNDUP(oa->oa_length) / sizeof (*buf); */ } } return (TRUE); }
/* * XXX - This is a shorter version of vattr_to_fattr4 which only takes care * of setattr args - size, mode, uid/gid, times. Eventually we should generalize * by using nfs4_ntov_map and the same functions used by the server. * Here we just hardcoded the setattr attributes. Note that the order is * important - it should follow the order of the bits in the mask. */ int vattr_to_fattr4(vattr_t *vap, vsecattr_t *vsap, fattr4 *fattrp, int flags, enum nfs_opnum4 op, bitmap4 supp) { int i, j; union nfs4_attr_u *na = NULL; int attrcnt; int uid_attr = -1; int gid_attr = -1; int acl_attr = -1; XDR xdr; ulong_t xdr_size; char *xdr_attrs; int error = 0; uint8_t amap[NFS4_MAXNUM_ATTRS]; uint_t va_mask = vap->va_mask; bool_t (*attrfunc)(); #ifndef lint /* * Make sure that maximum attribute number can be expressed as an * 8 bit quantity. */ ASSERT(NFS4_MAXNUM_ATTRS <= (UINT8_MAX + 1)); #endif fattrp->attrmask = 0; fattrp->attrlist4_len = 0; fattrp->attrlist4 = NULL; na = kmem_zalloc(sizeof (union nfs4_attr_u) * nfs4_ntov_map_size, KM_SLEEP); if (op == OP_SETATTR || op == OP_CREATE || op == OP_OPEN) { /* * Note we need to set the attrmask for set operations. * In particular mtime and atime will be set to the * servers time. */ nfs4_vmask_to_nmask_set(va_mask, &fattrp->attrmask); if (vsap != NULL) fattrp->attrmask |= FATTR4_ACL_MASK; attrfunc = nfs4_set_fattr4_attr; } else { /* verify/nverify */ /* * Verfy/nverify use the "normal vmask_to_nmask * this routine knows how to handle all vmask bits */ nfs4_vmask_to_nmask(va_mask, &fattrp->attrmask); /* * XXX verify/nverify only works for a subset of attrs that * directly map to vattr_t attrs. So, verify/nverify is * broken for servers that only support mandatory attrs. * Mask out change attr for now and fix verify op to * work with mandonly servers later. nfs4_vmask_to_nmask * sets change whenever it sees request for ctime/mtime, * so we must turn off change because nfs4_ver_fattr4_attr * will not generate args for change. This is a bug * that will be fixed later. * XXX */ fattrp->attrmask &= ~FATTR4_CHANGE_MASK; attrfunc = nfs4_ver_fattr4_attr; } /* Mask out any rec attrs unsupported by server */ fattrp->attrmask &= supp; attrcnt = 0; xdr_size = 0; for (i = 0; i < nfs4_ntov_map_size; i++) { /* * In the case of FATTR4_ACL_MASK, the vbit will be 0 (zero) * so we must also check if the fbit is FATTR4_ACL_MASK before * skipping over this attribute. */ if (!(nfs4_ntov_map[i].vbit & vap->va_mask)) { if (nfs4_ntov_map[i].fbit != FATTR4_ACL_MASK) continue; if (vsap == NULL) continue; } if (attrfunc == nfs4_set_fattr4_attr) { if (!(*attrfunc)(vap, vsap, &nfs4_ntov_map[i], &na[attrcnt], flags, &error)) continue; } else if (attrfunc == nfs4_ver_fattr4_attr) { if (!(*attrfunc)(vap, &nfs4_ntov_map[i], &na[attrcnt], flags, &error)) continue; } if (error) goto done; /* Exit! */ /* * Calculate XDR size */ if (nfs4_ntov_map[i].xdr_size != 0) { /* * If we are setting attributes (attrfunc is * nfs4_set_fattr4_attr) and are setting the * mtime or atime, adjust the xdr size down by * 3 words, since we are using the server's * time as the current time. Exception: if * ATTR_UTIME is set, the client sends the * time, so leave the xdr size alone. */ xdr_size += nfs4_ntov_map[i].xdr_size; if ((nfs4_ntov_map[i].nval == FATTR4_TIME_ACCESS_SET || nfs4_ntov_map[i].nval == FATTR4_TIME_MODIFY_SET) && attrfunc == nfs4_set_fattr4_attr && !(flags & ATTR_UTIME)) { xdr_size -= 3 * BYTES_PER_XDR_UNIT; } } else { /* * The only zero xdr_sizes we should see * are AT_UID, AT_GID and FATTR4_ACL_MASK */ ASSERT(nfs4_ntov_map[i].vbit == AT_UID || nfs4_ntov_map[i].vbit == AT_GID || nfs4_ntov_map[i].fbit == FATTR4_ACL_MASK); if (nfs4_ntov_map[i].vbit == AT_UID) { uid_attr = attrcnt; xdr_size += BYTES_PER_XDR_UNIT; /* length */ xdr_size += RNDUP(na[attrcnt].owner.utf8string_len); } else if (nfs4_ntov_map[i].vbit == AT_GID) { gid_attr = attrcnt; xdr_size += BYTES_PER_XDR_UNIT; /* length */ xdr_size += RNDUP( na[attrcnt].owner_group.utf8string_len); } else if (nfs4_ntov_map[i].fbit == FATTR4_ACL_MASK) { nfsace4 *tmpacl = (nfsace4 *)vsap->vsa_aclentp; acl_attr = attrcnt; /* fattr4_acl_len */ xdr_size += BYTES_PER_XDR_UNIT; /* fattr4_acl_val */ xdr_size += RNDUP((vsap->vsa_aclcnt * (sizeof (acetype4) + sizeof (aceflag4) + sizeof (acemask4)))); for (j = 0; j < vsap->vsa_aclcnt; j++) { /* who - utf8string_len */ xdr_size += BYTES_PER_XDR_UNIT; /* who - utf8string_val */ xdr_size += RNDUP(tmpacl[j].who.utf8string_len); } } } /* * This attr is going otw */ amap[attrcnt] = (uint8_t)nfs4_ntov_map[i].nval; attrcnt++; /* * Clear this bit from test mask so we stop * as soon as all requested attrs are done. */ va_mask &= ~nfs4_ntov_map[i].vbit; if (va_mask == 0 && (vsap == NULL || (vsap != NULL && acl_attr != -1))) break; } if (attrcnt == 0) { goto done; } fattrp->attrlist4 = xdr_attrs = kmem_alloc(xdr_size, KM_SLEEP); fattrp->attrlist4_len = xdr_size; xdrmem_create(&xdr, xdr_attrs, xdr_size, XDR_ENCODE); for (i = 0; i < attrcnt; i++) { if ((*nfs4_ntov_map[amap[i]].xfunc)(&xdr, &na[i]) == FALSE) { cmn_err(CE_WARN, "vattr_to_fattr4: xdr encode of " "attribute failed\n"); error = EINVAL; break; } } done: /* * Free any malloc'd attrs, can only be uid or gid */ if (uid_attr != -1 && na[uid_attr].owner.utf8string_val != NULL) { kmem_free(na[uid_attr].owner.utf8string_val, na[uid_attr].owner.utf8string_len); } if (gid_attr != -1 && na[gid_attr].owner_group.utf8string_val != NULL) { kmem_free(na[gid_attr].owner_group.utf8string_val, na[gid_attr].owner_group.utf8string_len); } /* xdrmem_destroy(&xdrs); */ /* NO-OP */ kmem_free(na, sizeof (union nfs4_attr_u) * nfs4_ntov_map_size); if (error) nfs4_fattr4_free(fattrp); return (error); }
enum auth_stat svcbyz_auth_unix(struct svc_req *rqst, struct rpc_msg *msg) { register enum auth_stat stat; XDR xdrs; register struct authunix_parms *aup; register int *buf; struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME+1]; unsigned int area_gids[NGRPS]; // JC: changed to unsigned } *area; u_int auth_len; int str_len, gid_len; register int i; area = (struct area *) rqst->rq_clntcred; aup = &area->area_aup; aup->aup_machname = area->area_machname; aup->aup_gids = area->area_gids; auth_len = (unsigned int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { aup->aup_time = IXDR_GET_LONG(buf); str_len = IXDR_GET_U_LONG(buf); if (str_len > MAX_MACHINE_NAME) { stat = AUTH_BADCRED; goto done; } bcopy((caddr_t)buf, aup->aup_machname, (u_int)str_len); aup->aup_machname[str_len] = 0; str_len = RNDUP(str_len); buf += str_len / sizeof(int); aup->aup_uid = IXDR_GET_LONG(buf); aup->aup_gid = IXDR_GET_LONG(buf); gid_len = IXDR_GET_U_LONG(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } aup->aup_len = gid_len; for (i = 0; i < gid_len; i++) { aup->aup_gids[i] = IXDR_GET_LONG(buf); } /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { (void) printf("bad auth_len gid %d str %d auth %d\n", gid_len, str_len, auth_len); stat = AUTH_BADCRED; goto done; } } else if (! xdr_authunix_parms(&xdrs, aup)) { xdrs.x_op = XDR_FREE; (void)xdr_authunix_parms(&xdrs, aup); stat = AUTH_BADCRED; goto done; } rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; rqst->rq_xprt->xp_verf.oa_length = 0; stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); }
/* * Unix longhand authenticator */ enum auth_stat _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) { enum auth_stat stat; XDR xdrs; struct authunix_parms *aup; int32_t *buf; struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME+1]; int area_gids[NGRPS]; } *area; u_int auth_len; size_t str_len, gid_len; u_int i; assert(rqst != NULL); assert(msg != NULL); area = (struct area *) rqst->rq_clntcred; aup = &area->area_aup; aup->aup_machname = area->area_machname; aup->aup_gids = area->area_gids; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { aup->aup_time = IXDR_GET_INT32(buf); str_len = (size_t)IXDR_GET_U_INT32(buf); if (str_len > MAX_MACHINE_NAME) { stat = AUTH_BADCRED; goto done; } memmove(aup->aup_machname, buf, str_len); aup->aup_machname[str_len] = 0; str_len = RNDUP(str_len); buf += str_len / sizeof (int32_t); aup->aup_uid = (int)IXDR_GET_INT32(buf); aup->aup_gid = (int)IXDR_GET_INT32(buf); gid_len = (size_t)IXDR_GET_U_INT32(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } aup->aup_len = gid_len; for (i = 0; i < gid_len; i++) { aup->aup_gids[i] = (int)IXDR_GET_INT32(buf); } /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { printf("bad auth_len gid %ld str %ld auth %u\n", (long)gid_len, (long)str_len, auth_len); stat = AUTH_BADCRED; goto done; } } else if (! xdr_authunix_parms(&xdrs, aup)) { xdrs.x_op = XDR_FREE; xdr_authunix_parms(&xdrs, aup); stat = AUTH_BADCRED; goto done; } /* get the verifier */ if ((u_int)msg->rm_call.cb_verf.oa_length) { rqst->rq_xprt->xp_verf.oa_flavor = msg->rm_call.cb_verf.oa_flavor; rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; rqst->rq_xprt->xp_verf.oa_length = msg->rm_call.cb_verf.oa_length; } else { rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; rqst->rq_xprt->xp_verf.oa_length = 0; } stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); }
static void init_mem_alloc(void) { int local; /* variables needed to find start region */ paddr_t scratch_start; xen_memory_map_t map; DBG_MSG("Entered init_mem_alloc()\n"); /* * Free memory follows the stack. There's at least 512KB of scratch * space, rounded up to at least 2Mb alignment. That should be enough * for the page tables we'll need to build. The nucleus memory is * allocated last and will be outside the addressible range. We'll * switch to new page tables before we unpack the kernel */ scratch_start = RNDUP((paddr_t)(uintptr_t)&local, MMU_PAGESIZE); DBG(scratch_start); scratch_end = RNDUP((paddr_t)scratch_start + 512 * 1024, TWO_MEG); DBG(scratch_end); /* * For paranoia, leave some space between hypervisor data and ours. * Use 500 instead of 512. */ next_avail_addr = scratch_end - 500 * 1024; DBG(next_avail_addr); /* * The domain builder gives us at most 1 module */ DBG(xen_info->mod_len); if (xen_info->mod_len > 0) { DBG(xen_info->mod_start); modules[0].bm_addr = xen_info->mod_start; modules[0].bm_size = xen_info->mod_len; bi->bi_module_cnt = 1; bi->bi_modules = (native_ptr_t)modules; } else { bi->bi_module_cnt = 0; bi->bi_modules = NULL; } DBG(bi->bi_module_cnt); DBG(bi->bi_modules); DBG(xen_info->mfn_list); DBG(xen_info->nr_pages); max_mem = (paddr_t)xen_info->nr_pages << MMU_PAGESHIFT; DBG(max_mem); /* * Using pseudo-physical addresses, so only 1 memlist element */ memlists[0].addr = 0; DBG(memlists[0].addr); memlists[0].size = max_mem; DBG(memlists[0].size); memlists_used = 1; DBG(memlists_used); /* * finish building physinstall list */ sort_physinstall(); /* * build bios reserved memlists */ build_rsvdmemlists(); if (DOMAIN_IS_INITDOMAIN(xen_info)) { /* * build PCI Memory list */ map.nr_entries = MAXMAPS; /*LINTED: constant in conditional context*/ set_xen_guest_handle(map.buffer, map_buffer); if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &map) != 0) dboot_panic("getting XENMEM_machine_memory_map failed"); build_pcimemlists(map_buffer, map.nr_entries); } }
/* * XDR for unix authentication parameters. */ bool_t xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) { uint32_t namelen; uint32_t ngroups, i; uint32_t junk; char hostbuf[MAXHOSTNAMELEN]; if (xdrs->x_op == XDR_ENCODE) { /* * Restrict name length to 255 according to RFC 1057. */ getcredhostname(NULL, hostbuf, sizeof(hostbuf)); namelen = strlen(hostbuf); if (namelen > 255) namelen = 255; } else { namelen = 0; } junk = 0; if (!xdr_uint32_t(xdrs, time) || !xdr_uint32_t(xdrs, &namelen)) return (FALSE); /* * Ignore the hostname on decode. */ if (xdrs->x_op == XDR_ENCODE) { if (!xdr_opaque(xdrs, hostbuf, namelen)) return (FALSE); } else { xdr_setpos(xdrs, xdr_getpos(xdrs) + RNDUP(namelen)); } if (!xdr_uint32_t(xdrs, &cred->cr_uid)) return (FALSE); if (!xdr_uint32_t(xdrs, &cred->cr_groups[0])) return (FALSE); if (xdrs->x_op == XDR_ENCODE) { ngroups = cred->cr_ngroups - 1; if (ngroups > NGRPS) ngroups = NGRPS; } if (!xdr_uint32_t(xdrs, &ngroups)) return (FALSE); for (i = 0; i < ngroups; i++) { if (i + 1 < ngroups_max + 1) { if (!xdr_uint32_t(xdrs, &cred->cr_groups[i + 1])) return (FALSE); } else { if (!xdr_uint32_t(xdrs, &junk)) return (FALSE); } } if (xdrs->x_op == XDR_DECODE) { if (ngroups + 1 > ngroups_max + 1) cred->cr_ngroups = ngroups_max + 1; else cred->cr_ngroups = ngroups + 1; } return (TRUE); }
/* * Door IPC based client creation routine. * * NB: The rpch->cl_auth is initialized to null authentication. * Caller may wish to set this something more useful. * * sendsz is the maximum allowable packet size that can be sent. * 0 will cause default to be used. */ CLIENT * clnt_door_create(const rpcprog_t program, const rpcvers_t version, const uint_t sendsz) { CLIENT *cl = NULL; /* client handle */ struct cu_data *cu = NULL; /* private data */ struct rpc_msg call_msg; char rendezvous[64]; int did; struct door_info info; XDR xdrs; struct timeval now; uint_t ssz; (void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)program, (int)version); if ((did = open(rendezvous, O_RDONLY, 0)) < 0) { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; rpc_createerr.cf_error.re_errno = errno; rpc_createerr.cf_error.re_terrno = 0; return (NULL); } if (door_info(did, &info) < 0 || (info.di_attributes & DOOR_REVOKED)) { (void) close(did); rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; rpc_createerr.cf_error.re_errno = errno; rpc_createerr.cf_error.re_terrno = 0; return (NULL); } /* * Determine send size */ if (sendsz < __rpc_min_door_buf_size) ssz = __rpc_default_door_buf_size; else ssz = RNDUP(sendsz); if ((cl = malloc(sizeof (CLIENT))) == NULL || (cu = malloc(sizeof (*cu))) == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } /* * Precreate RPC header for performance reasons. */ (void) gettimeofday(&now, NULL); call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; xdrmem_create(&xdrs, cu->cu_header, sizeof (cu->cu_header), XDR_ENCODE); if (!xdr_callhdr(&xdrs, &call_msg)) { rpc_createerr.cf_stat = RPC_CANTENCODEARGS; rpc_createerr.cf_error.re_errno = 0; goto err; } cu->cu_xdrpos = XDR_GETPOS(&xdrs); cu->cu_sendsz = ssz; cu->cu_fd = did; cu->cu_closeit = TRUE; cl->cl_ops = clnt_door_ops(); cl->cl_private = (caddr_t)cu; cl->cl_auth = authnone_create(); cl->cl_tp = strdup(rendezvous); if (cl->cl_tp == NULL) { syslog(LOG_ERR, "clnt_door_create: strdup failed"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } cl->cl_netid = strdup("door"); if (cl->cl_netid == NULL) { syslog(LOG_ERR, "clnt_door_create: strdup failed"); if (cl->cl_tp) free(cl->cl_tp); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } return (cl); err: rpc_createerr.cf_error.re_terrno = 0; if (cl) { free(cl); if (cu) free(cu); } (void) close(did); return (NULL); }
/* * Slightly modified version of authdessec_create which takes the public key * of the server principal as an argument. This spares us a call to * getpublickey() which in the nameserver context can cause a deadlock. */ AUTH * authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window, const char *timehost, const des_block *ckey, nis_server *srvr) { AUTH *auth; struct ad_private *ad; char namebuf[MAXNETNAMELEN+1]; /* * Allocate everything now */ auth = ALLOC(AUTH); if (auth == NULL) { syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); return (NULL); } ad = ALLOC(struct ad_private); if (ad == NULL) { syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); goto failed; } ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ ad->ad_timehost = NULL; ad->ad_netid = NULL; ad->ad_uaddr = NULL; ad->ad_nis_srvr = NULL; ad->ad_timediff.tv_sec = 0; ad->ad_timediff.tv_usec = 0; memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); if (!getnetname(namebuf)) goto failed; ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); ad->ad_servernamelen = strlen(servername); ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { syslog(LOG_ERR, "authdes_seccreate: out of memory"); goto failed; } if (timehost != NULL) { ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1); if (ad->ad_timehost == NULL) { syslog(LOG_ERR, "authdes_seccreate: out of memory"); goto failed; } memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); ad->ad_dosync = TRUE; } else if (srvr != NULL) { ad->ad_nis_srvr = srvr; /* transient */ ad->ad_dosync = TRUE; } else { ad->ad_dosync = FALSE; } memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); ad->ad_window = window; if (ckey == NULL) { if (key_gendes(&auth->ah_key) < 0) { syslog(LOG_ERR, "authdes_seccreate: keyserv(1m) is unable to generate session key"); goto failed; } } else { auth->ah_key = *ckey; } /* * Set up auth handle */ auth->ah_cred.oa_flavor = AUTH_DES; auth->ah_verf.oa_flavor = AUTH_DES; auth->ah_ops = authdes_ops(); auth->ah_private = (caddr_t)ad; if (!authdes_refresh(auth, NULL)) { goto failed; } ad->ad_nis_srvr = NULL; /* not needed any longer */ return (auth); failed: if (auth) FREE(auth, sizeof (AUTH)); if (ad) { if (ad->ad_fullname) FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); if (ad->ad_servername) FREE(ad->ad_servername, ad->ad_servernamelen + 1); if (ad->ad_timehost) FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); if (ad->ad_netid) FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); if (ad->ad_uaddr) FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); FREE(ad, sizeof (struct ad_private)); } return (NULL); }
/* * Arguments to remote write and writecache */ bool_t xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa) { int32_t *ptr; int32_t *fhp; switch (xdrs->x_op) { case XDR_DECODE: wa->wa_args = &wa->wa_args_buf; ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT); if (ptr != NULL) { fhp = (int32_t *)&wa->wa_fhandle; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp++ = *ptr++; *fhp = *ptr++; wa->wa_begoff = IXDR_GET_U_INT32(ptr); wa->wa_offset = IXDR_GET_U_INT32(ptr); wa->wa_totcount = IXDR_GET_U_INT32(ptr); wa->wa_mblk = NULL; wa->wa_data = NULL; wa->wa_rlist = NULL; wa->wa_conn = NULL; if (xdrs->x_ops == &xdrmblk_ops) { return (xdrmblk_getmblk(xdrs, &wa->wa_mblk, &wa->wa_count)); } else { if (xdrs->x_ops == &xdrrdmablk_ops) { if (xdrrdma_getrdmablk(xdrs, &wa->wa_rlist, &wa->wa_count, &wa->wa_conn, NFS_MAXDATA) == TRUE) return (xdrrdma_read_from_client( wa->wa_rlist, &wa->wa_conn, wa->wa_count)); wa->wa_rlist = NULL; wa->wa_conn = NULL; } } /* * It is just as efficient to xdr_bytes * an array of unknown length as to inline copy it. */ return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count, NFS_MAXDATA)); } if (xdr_fhandle(xdrs, &wa->wa_fhandle) && xdr_u_int(xdrs, &wa->wa_begoff) && xdr_u_int(xdrs, &wa->wa_offset) && xdr_u_int(xdrs, &wa->wa_totcount)) { /* deal with the variety of data transfer types */ wa->wa_mblk = NULL; wa->wa_data = NULL; wa->wa_rlist = NULL; wa->wa_conn = NULL; if (xdrs->x_ops == &xdrmblk_ops) { if (xdrmblk_getmblk(xdrs, &wa->wa_mblk, &wa->wa_count) == TRUE) return (TRUE); } else { if (xdrs->x_ops == &xdrrdmablk_ops) { if (xdrrdma_getrdmablk(xdrs, &wa->wa_rlist, &wa->wa_count, &wa->wa_conn, NFS_MAXDATA) == TRUE) return (xdrrdma_read_from_client( wa->wa_rlist, &wa->wa_conn, wa->wa_count)); wa->wa_rlist = NULL; wa->wa_conn = NULL; } } return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count, NFS_MAXDATA)); } return (FALSE); case XDR_ENCODE: ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT); if (ptr != NULL) { fhp = (int32_t *)&wa->wa_fhandle; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp++; *ptr++ = *fhp; IXDR_PUT_U_INT32(ptr, wa->wa_begoff); IXDR_PUT_U_INT32(ptr, wa->wa_offset); IXDR_PUT_U_INT32(ptr, wa->wa_totcount); } else { if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) && xdr_u_int(xdrs, &wa->wa_begoff) && xdr_u_int(xdrs, &wa->wa_offset) && xdr_u_int(xdrs, &wa->wa_totcount))) return (FALSE); } return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count, NFS_MAXDATA)); case XDR_FREE: if (wa->wa_rlist) { (void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist); wa->wa_rlist = NULL; } if (wa->wa_data != NULL) { kmem_free(wa->wa_data, wa->wa_count); wa->wa_data = NULL; } return (TRUE); } return (FALSE); }
/* * Unix longhand authenticator */ enum auth_stat _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) { enum auth_stat stat; XDR xdrs; int32_t *buf; uint32_t time; struct xucred *xcr; u_int auth_len; size_t str_len, gid_len; u_int i; xcr = rqst->rq_clntcred; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE); buf = XDR_INLINE(&xdrs, auth_len); if (buf != NULL) { time = IXDR_GET_UINT32(buf); str_len = (size_t)IXDR_GET_UINT32(buf); if (str_len > MAX_MACHINE_NAME) { stat = AUTH_BADCRED; goto done; } str_len = RNDUP(str_len); buf += str_len / sizeof (int32_t); xcr->cr_uid = IXDR_GET_UINT32(buf); xcr->cr_groups[0] = IXDR_GET_UINT32(buf); gid_len = (size_t)IXDR_GET_UINT32(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } for (i = 0; i < gid_len; i++) { if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); else buf++; } if (gid_len + 1 > XU_NGROUPS) xcr->cr_ngroups = XU_NGROUPS; else xcr->cr_ngroups = gid_len + 1; /* * five is the smallest unix credentials structure - * timestamp, hostname len (0), uid, gid, and gids len (0). */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { (void) printf("bad auth_len gid %ld str %ld auth %u\n", (long)gid_len, (long)str_len, auth_len); stat = AUTH_BADCRED; goto done; } } else if (! xdr_authunix_parms(&xdrs, &time, xcr)) { stat = AUTH_BADCRED; goto done; } rqst->rq_verf = _null_auth; stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); }