void proxy_get_account_info(struct be_req *breq) { struct be_ctx *be_ctx = be_req_get_be_ctx(breq); struct be_acct_req *ar; struct proxy_id_ctx *ctx; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; uid_t uid; gid_t gid; int ret; char *endptr; ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req); ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, struct proxy_id_ctx); sysdb = be_ctx->domain->sysdb; domain = be_ctx->domain; if (be_is_offline(be_ctx)) { return be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline"); } /* for now we support only core attrs */ if (ar->attr_type != BE_ATTR_CORE) { return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type"); } /* proxy provider does not support security ID lookups */ if (ar->filter_type == BE_FILTER_SECID) { return be_req_terminate(breq, DP_ERR_FATAL, ENOSYS, "Invalid filter type"); } switch (ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ switch (ar->filter_type) { case BE_FILTER_ENUM: ret = enum_users(breq, ctx, sysdb, domain); break; case BE_FILTER_NAME: ret = get_pw_name(ctx, domain, ar->filter_value); break; case BE_FILTER_IDNUM: uid = (uid_t) strtouint32(ar->filter_value, &endptr, 10); if (errno || *endptr || (ar->filter_value == endptr)) { return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type"); } ret = get_pw_uid(ctx, domain, uid); break; default: return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } break; case BE_REQ_GROUP: /* group */ switch (ar->filter_type) { case BE_FILTER_ENUM: ret = enum_groups(breq, ctx, sysdb, domain); break; case BE_FILTER_NAME: ret = get_gr_name(ctx, sysdb, domain, ar->filter_value); break; case BE_FILTER_IDNUM: gid = (gid_t) strtouint32(ar->filter_value, &endptr, 10); if (errno || *endptr || (ar->filter_value == endptr)) { return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type"); } ret = get_gr_gid(breq, ctx, sysdb, domain, gid, 0); break; default: return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } break; case BE_REQ_INITGROUPS: /* init groups for user */ if (ar->filter_type != BE_FILTER_NAME) { return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } if (ctx->ops.initgroups_dyn == NULL) { return be_req_terminate(breq, DP_ERR_FATAL, ENODEV, "Initgroups call not supported"); } ret = get_initgr(breq, ctx, sysdb, domain, ar->filter_value); break; case BE_REQ_NETGROUP: if (ar->filter_type != BE_FILTER_NAME) { return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL || ctx->ops.endnetgrent == NULL) { return be_req_terminate(breq, DP_ERR_FATAL, ENODEV, "Netgroups are not supported"); } ret = get_netgroup(ctx, domain, ar->filter_value); break; case BE_REQ_SERVICES: switch (ar->filter_type) { case BE_FILTER_NAME: if (ctx->ops.getservbyname_r == NULL) { return be_req_terminate(breq, DP_ERR_FATAL, ENODEV, "Services are not supported"); } ret = get_serv_byname(ctx, domain, ar->filter_value, ar->extra_value); break; case BE_FILTER_IDNUM: if (ctx->ops.getservbyport_r == NULL) { return be_req_terminate(breq, DP_ERR_FATAL, ENODEV, "Services are not supported"); } ret = get_serv_byport(ctx, domain, ar->filter_value, ar->extra_value); break; case BE_FILTER_ENUM: if (!ctx->ops.setservent || !ctx->ops.getservent_r || !ctx->ops.endservent) { return be_req_terminate(breq, DP_ERR_FATAL, ENODEV, "Services are not supported"); } ret = enum_services(ctx, sysdb, domain); break; default: return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } break; default: /*fail*/ return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid request type"); } if (ret) { if (ret == ENXIO) { DEBUG(SSSDBG_OP_FAILURE, "proxy returned UNAVAIL error, going offline!\n"); be_mark_offline(be_ctx); } be_req_terminate(breq, DP_ERR_FATAL, ret, NULL); return; } be_req_terminate(breq, DP_ERR_OK, EOK, NULL); }
static struct dp_reply_std proxy_account_info(TALLOC_CTX *mem_ctx, struct proxy_id_ctx *ctx, struct dp_id_data *data, struct be_ctx *be_ctx, struct sss_domain_info *domain) { struct dp_reply_std reply; struct sysdb_ctx *sysdb; uid_t uid; gid_t gid; errno_t ret; char *endptr; sysdb = domain->sysdb; /* For now we support only core attrs. */ if (data->attr_type != BE_ATTR_CORE) { dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid attr type"); return reply; } /* Proxy provider does not support security ID lookups. */ if (data->filter_type == BE_FILTER_SECID) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENOSYS, "Security lookups are not supported"); return reply; } switch (data->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ switch (data->filter_type) { case BE_FILTER_ENUM: ret = enum_users(mem_ctx, ctx, sysdb, domain); break; case BE_FILTER_NAME: ret = get_pw_name(ctx, domain, data->filter_value); break; case BE_FILTER_IDNUM: uid = (uid_t) strtouint32(data->filter_value, &endptr, 10); if (errno || *endptr || (data->filter_value == endptr)) { dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid attr type"); return reply; } ret = get_pw_uid(ctx, domain, uid); break; default: dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } break; case BE_REQ_GROUP: /* group */ switch (data->filter_type) { case BE_FILTER_ENUM: ret = enum_groups(mem_ctx, ctx, sysdb, domain); break; case BE_FILTER_NAME: ret = get_gr_name(ctx, sysdb, domain, data->filter_value); break; case BE_FILTER_IDNUM: gid = (gid_t) strtouint32(data->filter_value, &endptr, 10); if (errno || *endptr || (data->filter_value == endptr)) { dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid attr type"); return reply; } ret = get_gr_gid(mem_ctx, ctx, sysdb, domain, gid, 0); break; default: dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } break; case BE_REQ_INITGROUPS: /* init groups for user */ if (data->filter_type != BE_FILTER_NAME) { dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } if (ctx->ops.initgroups_dyn == NULL) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, "Initgroups call not supported"); return reply; } ret = get_initgr(mem_ctx, ctx, sysdb, domain, data->filter_value); break; case BE_REQ_NETGROUP: if (data->filter_type != BE_FILTER_NAME) { dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL || ctx->ops.endnetgrent == NULL) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, "Netgroups are not supported"); return reply; } ret = get_netgroup(ctx, domain, data->filter_value); break; case BE_REQ_SERVICES: switch (data->filter_type) { case BE_FILTER_NAME: if (ctx->ops.getservbyname_r == NULL) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, "Services are not supported"); return reply; } ret = get_serv_byname(ctx, domain, data->filter_value, data->extra_value); break; case BE_FILTER_IDNUM: if (ctx->ops.getservbyport_r == NULL) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, "Services are not supported"); return reply; } ret = get_serv_byport(ctx, domain, data->filter_value, data->extra_value); break; case BE_FILTER_ENUM: if (!ctx->ops.setservent || !ctx->ops.getservent_r || !ctx->ops.endservent) { dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, "Services are not supported"); return reply; } ret = enum_services(ctx, sysdb, domain); break; default: dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } break; default: /*fail*/ dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, "Invalid filter type"); return reply; } if (ret) { if (ret == ENXIO) { DEBUG(SSSDBG_OP_FAILURE, "proxy returned UNAVAIL error, going offline!\n"); be_mark_offline(be_ctx); } dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL); return reply; } dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL); return reply; }
static int get_initgr_groups_process(TALLOC_CTX *memctx, struct proxy_id_ctx *ctx, struct sysdb_ctx *sysdb, struct sss_domain_info *dom, struct passwd *pwd) { enum nss_status status; long int limit; long int size; long int num; long int num_gids; gid_t *gids; int ret; int i; time_t now; num_gids = 0; limit = 4096; num = 4096; size = num*sizeof(gid_t); gids = talloc_size(memctx, size); if (!gids) { return ENOMEM; } /* nss modules may skip the primary group when we pass it in so always add * it in advance */ gids[0] = pwd->pw_gid; num_gids++; /* FIXME: should we move this call outside the transaction to keep the * transaction as short as possible ? */ do { status = ctx->ops.initgroups_dyn(pwd->pw_name, pwd->pw_gid, &num_gids, &num, &gids, limit, &ret); if (status == NSS_STATUS_TRYAGAIN) { /* buffer too small ? */ if (size < MAX_BUF_SIZE) { num *= 2; size = num*sizeof(gid_t); } if (size > MAX_BUF_SIZE) { size = MAX_BUF_SIZE; num = size/sizeof(gid_t); } limit = num; gids = talloc_realloc_size(memctx, gids, size); if (!gids) { return ENOMEM; } } } while(status == NSS_STATUS_TRYAGAIN); switch (status) { case NSS_STATUS_NOTFOUND: DEBUG(SSSDBG_FUNC_DATA, "The initgroups call returned 'NOTFOUND'. " "Assume the user is only member of its " "primary group (%"SPRIgid")\n", pwd->pw_gid); /* fall through */ case NSS_STATUS_SUCCESS: DEBUG(SSSDBG_CONF_SETTINGS, "User [%s] appears to be member of %lu " "groups\n", pwd->pw_name, num_gids); now = time(NULL); for (i = 0; i < num_gids; i++) { ret = get_gr_gid(memctx, ctx, sysdb, dom, gids[i], now); if (ret) { return ret; } } ret = EOK; break; default: DEBUG(SSSDBG_OP_FAILURE, "proxy -> initgroups_dyn failed (%d)[%s]\n", ret, strerror(ret)); ret = EIO; break; } return ret; }
static int get_initgr_groups_process(TALLOC_CTX *memctx, struct proxy_id_ctx *ctx, struct sysdb_ctx *sysdb, struct sss_domain_info *dom, struct passwd *pwd) { enum nss_status status; long int limit; long int size; long int num; long int num_gids; gid_t *gids; int ret; int i; time_t now; num_gids = 0; limit = 4096; num = 4096; size = num*sizeof(gid_t); gids = talloc_size(memctx, size); if (!gids) { return ENOMEM; } /* FIXME: should we move this call outside the transaction to keep the * transaction as short as possible ? */ do { status = ctx->ops.initgroups_dyn(pwd->pw_name, pwd->pw_gid, &num_gids, &num, &gids, limit, &ret); if (status == NSS_STATUS_TRYAGAIN) { /* buffer too small ? */ if (size < MAX_BUF_SIZE) { num *= 2; size = num*sizeof(gid_t); } if (size > MAX_BUF_SIZE) { size = MAX_BUF_SIZE; num = size/sizeof(gid_t); } limit = num; gids = talloc_realloc_size(memctx, gids, size); if (!gids) { return ENOMEM; } } } while(status == NSS_STATUS_TRYAGAIN); switch (status) { case NSS_STATUS_SUCCESS: DEBUG(SSSDBG_CONF_SETTINGS, ("User [%s] appears to be member of %lu" "groups\n", pwd->pw_name, num_gids)); now = time(NULL); for (i = 0; i < num_gids; i++) { ret = get_gr_gid(memctx, ctx, sysdb, dom, gids[i], now); if (ret) { return ret; } } ret = EOK; break; default: DEBUG(2, ("proxy -> initgroups_dyn failed (%d)[%s]\n", ret, strerror(ret))); ret = EIO; break; } return ret; }