int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer) { int len; uint8_t *buf; size_t rp; len = sizeof(uint32_t) + 2*sizeof(uint32_t) + pi->pam_user_size + sizeof(uint32_t); len += *pi->pam_service != '\0' ? 2*sizeof(uint32_t) + pi->pam_service_size : 0; len += *pi->pam_tty != '\0' ? 2*sizeof(uint32_t) + pi->pam_tty_size : 0; len += *pi->pam_ruser != '\0' ? 2*sizeof(uint32_t) + pi->pam_ruser_size : 0; len += *pi->pam_rhost != '\0' ? 2*sizeof(uint32_t) + pi->pam_rhost_size : 0; len += pi->pam_authtok != NULL ? 3*sizeof(uint32_t) + pi->pam_authtok_size : 0; len += pi->pam_newauthtok != NULL ? 3*sizeof(uint32_t) + pi->pam_newauthtok_size : 0; len += 3*sizeof(uint32_t); /* cli_pid */ len += *pi->requested_domains != '\0' ? 2*sizeof(uint32_t) + pi->requested_domains_size : 0; buf = malloc(len); if (buf == NULL) { D(("malloc failed.")); return PAM_BUF_ERR; } rp = 0; SAFEALIGN_SETMEM_UINT32(buf, SSS_START_OF_PAM_REQUEST, &rp); rp += add_string_item(SSS_PAM_ITEM_USER, pi->pam_user, pi->pam_user_size, &buf[rp]); rp += add_string_item(SSS_PAM_ITEM_SERVICE, pi->pam_service, pi->pam_service_size, &buf[rp]); rp += add_string_item(SSS_PAM_ITEM_TTY, pi->pam_tty, pi->pam_tty_size, &buf[rp]); rp += add_string_item(SSS_PAM_ITEM_RUSER, pi->pam_ruser, pi->pam_ruser_size, &buf[rp]); rp += add_string_item(SSS_PAM_ITEM_RHOST, pi->pam_rhost, pi->pam_rhost_size, &buf[rp]); rp += add_string_item(SSS_PAM_ITEM_REQUESTED_DOMAINS, pi->requested_domains, pi->requested_domains_size, &buf[rp]); rp += add_uint32_t_item(SSS_PAM_ITEM_CLI_PID, (uint32_t) pi->cli_pid, &buf[rp]); rp += add_authtok_item(SSS_PAM_ITEM_AUTHTOK, pi->pam_authtok_type, pi->pam_authtok, pi->pam_authtok_size, &buf[rp]); rp += add_authtok_item(SSS_PAM_ITEM_NEWAUTHTOK, pi->pam_newauthtok_type, pi->pam_newauthtok, pi->pam_newauthtok_size, &buf[rp]); SAFEALIGN_SETMEM_UINT32(buf + rp, SSS_END_OF_PAM_REQUEST, &rp); if (rp != len) { D(("error during packet creation.")); free(buf); return PAM_BUF_ERR; } *size = len; *buffer = buf; return 0; }
errno_t nss_protocol_fill_pwent(struct nss_ctx *nss_ctx, struct nss_cmd_ctx *cmd_ctx, struct sss_packet *packet, struct cache_req_result *result) { TALLOC_CTX *tmp_ctx; struct ldb_message *msg; struct sized_string pwfield; struct sized_string *name; struct sized_string gecos; struct sized_string homedir; struct sized_string shell; uint32_t gid; uint32_t uid; uint32_t num_results; size_t rp; size_t body_len; uint8_t *body; int i; errno_t ret; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } /* First two fields (length and reserved), filled up later. */ ret = sss_packet_grow(packet, 2 * sizeof(uint32_t)); if (ret != EOK) { return ret; } rp = 2 * sizeof(uint32_t); num_results = 0; for (i = 0; i < result->count; i++) { talloc_free_children(tmp_ctx); msg = result->msgs[i]; /* Password field content. */ to_sized_string(&pwfield, nss_get_pwfield(nss_ctx, result->domain)); ret = nss_get_pwent(tmp_ctx, nss_ctx, result->domain, msg, &uid, &gid, &name, &gecos, &homedir, &shell); if (ret != EOK) { continue; } /* Adjust packet size: uid, gid + string fields. */ ret = sss_packet_grow(packet, 2 * sizeof(uint32_t) + name->len + gecos.len + homedir.len + shell.len + pwfield.len); if (ret != EOK) { goto done; } sss_packet_get_body(packet, &body, &body_len); /* Fill packet. */ SAFEALIGN_SET_UINT32(&body[rp], uid, &rp); SAFEALIGN_SET_UINT32(&body[rp], gid, &rp); SAFEALIGN_SET_STRING(&body[rp], name->str, name->len, &rp); SAFEALIGN_SET_STRING(&body[rp], pwfield.str, pwfield.len, &rp); SAFEALIGN_SET_STRING(&body[rp], gecos.str, gecos.len, &rp); SAFEALIGN_SET_STRING(&body[rp], homedir.str, homedir.len, &rp); SAFEALIGN_SET_STRING(&body[rp], shell.str, shell.len, &rp); num_results++; /* Do not store entry in memory cache during enumeration or when * requested. */ if (!cmd_ctx->enumeration && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) { ret = sss_mmap_cache_pw_store(&nss_ctx->pwd_mc_ctx, name, &pwfield, uid, gid, &gecos, &homedir, &shell); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Failed to store user %s (%s) in mmap cache [%d]: %s!\n", name->str, result->domain->name, ret, sss_strerror(ret)); } } } ret = EOK; done: talloc_free(tmp_ctx); if (ret != EOK) { sss_packet_set_size(packet, 0); return ret; } sss_packet_get_body(packet, &body, &body_len); SAFEALIGN_COPY_UINT32(body, &num_results, NULL); SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL); /* reserved */ return EOK; }