nis_error nis_removemember (const_nis_name member, const_nis_name group) { if (group != NULL && group[0] != '\0') { size_t grouplen = strlen (group); char buf[grouplen + 14 + NIS_MAXNAMELEN]; char leafbuf[grouplen + 2]; char domainbuf[grouplen + 2]; nis_name *newmem; nis_result *res, *res2; nis_error status; char *cp, *cp2; unsigned long int i, j, k; cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1)); cp = stpcpy (cp, ".groups_dir"); cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1); if (cp2 != NULL && cp2[0] != '\0') { cp = stpcpy (cp, "."); stpcpy (cp, cp2); } res = nis_lookup (buf, FOLLOW_LINKS|EXPAND_NAME); if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS) { if (res) { status = NIS_RES_STATUS (res); nis_freeresult (res); } else return NIS_NOMEMORY; return status; } if ((res->objects.objects_len != 1) || (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)) { nis_freeresult (res); return NIS_INVALIDOBJ; } newmem = calloc (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len, sizeof (char *)); if (newmem == NULL) return NIS_NOMEMORY; k = NIS_RES_OBJECT (res)[0].GR_data.gr_members.gr_members_len; j = 0; for (i = 0; i < NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len; ++i) { if (strcmp (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i], member) != 0) { newmem[j] = NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i]; ++j; } else { free (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val[i]); --k; } } free (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val); assert (k <= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len); /* This realloc() call always decreases the size. This cannot fail. We still have the test but do not recover memory (i.e., we overwrite the input pointer). */ nis_name *newp = realloc (newmem, k * sizeof (char*)); if (newp == NULL) { free (newmem); return NIS_NOMEMORY; } newmem = newp; NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val = newmem; NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len = k; cp = stpcpy (buf, NIS_RES_OBJECT (res)->zo_name); *cp++ = '.'; strncpy (cp, NIS_RES_OBJECT (res)->zo_domain, NIS_MAXNAMELEN); res2 = nis_modify (buf, NIS_RES_OBJECT (res)); status = NIS_RES_STATUS (res2); nis_freeresult (res); nis_freeresult (res2); return status; } else return NIS_FAIL; }
/* internal_nis_ismember () return codes: -1 principal is in -group 0 principal isn't in any group 1 pirncipal is in group */ static int internal_ismember (const_nis_name principal, const_nis_name group) { size_t grouplen = strlen (group); char buf[grouplen + 50]; char leafbuf[grouplen + 2]; char domainbuf[grouplen + 2]; nis_result *res; char *cp, *cp2; u_int i; cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1)); cp = stpcpy (cp, ".groups_dir"); cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1); if (cp2 != NULL && cp2[0] != '\0') { *cp++ = '.'; strcpy (cp, cp2); } res = nis_lookup (buf, EXPAND_NAME|FOLLOW_LINKS); if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS) { nis_freeresult (res); return 0; } if ((NIS_RES_NUMOBJ (res) != 1) || (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)) { nis_freeresult (res); return 0; } /* We search twice in the list, at first, if we have the name with a "-", then if without. "-member" has priority */ for (i = 0; i < NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len; ++i) { cp = NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i]; if (cp[0] == '-') { if (strcmp (&cp[1], principal) == 0) { nis_freeresult (res); return -1; } if (cp[1] == '@') switch (internal_ismember (principal, &cp[2])) { case -1: nis_freeresult (res); return -1; case 1: nis_freeresult (res); return 1; default: break; } else if (cp[1] == '*') { char buf1[strlen (principal) + 2]; char buf2[strlen (cp) + 2]; if (strcmp (nis_domain_of_r (principal, buf1, sizeof buf1), nis_domain_of_r (cp, buf2, sizeof buf2)) == 0) { nis_freeresult (res); return -1; } } } } for (i = 0; i < NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len; ++i) { cp = NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i]; if (cp[0] != '-') { if (strcmp (cp, principal) == 0) { nis_freeresult (res); return 1; } if (cp[0] == '@') switch (internal_ismember (principal, &cp[1])) { case -1: nis_freeresult (res); return -1; case 1: nis_freeresult (res); return 1; default: break; } else if (cp[0] == '*') { char buf1[strlen (principal) + 2]; char buf2[strlen (cp) + 2]; if (strcmp (nis_domain_of_r (principal, buf1, sizeof buf1), nis_domain_of_r (cp, buf2, sizeof buf2)) == 0) { nis_freeresult (res); return 1; } } } } nis_freeresult (res); return 0; }
nis_error nis_addmember (const_nis_name member, const_nis_name group) { if (group != NULL && group[0] != '\0') { size_t grouplen = strlen (group); char buf[grouplen + 14 + NIS_MAXNAMELEN]; char leafbuf[grouplen + 2]; char domainbuf[grouplen + 2]; nis_result *res, *res2; nis_error status; char *cp, *cp2; cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1)); cp = stpcpy (cp, ".groups_dir"); cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1); if (cp2 != NULL && cp2[0] != '\0') { *cp++ = '.'; stpcpy (cp, cp2); } res = nis_lookup (buf, FOLLOW_LINKS|EXPAND_NAME); if (NIS_RES_STATUS (res) != NIS_SUCCESS) { status = NIS_RES_STATUS (res); nis_freeresult (res); return status; } if ((NIS_RES_NUMOBJ (res) != 1) || (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)) { nis_freeresult (res); return NIS_INVALIDOBJ; } NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val = realloc (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val, (NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len + 1) * sizeof (char *)); if (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val == NULL) goto nomem_out; NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len] = strdup (member); if (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len] == NULL) { free (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val); nomem_out: nis_freeresult (res); return NIS_NOMEMORY; } ++NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len; /* Check the buffer bounds are not exceeded. */ assert (strlen (NIS_RES_OBJECT(res)->zo_name) + 1 < grouplen + 14); cp = stpcpy (buf, NIS_RES_OBJECT(res)->zo_name); *cp++ = '.'; strncpy (cp, NIS_RES_OBJECT (res)->zo_domain, NIS_MAXNAMELEN); res2 = nis_modify (buf, NIS_RES_OBJECT (res)); status = NIS_RES_STATUS (res2); nis_freeresult (res); nis_freeresult (res2); return status; } else return NIS_FAIL; }
nis_error nis_creategroup (const_nis_name group, unsigned int flags) { if (group != NULL && group[0] != '\0') { size_t grouplen = strlen (group); char buf[grouplen + 50]; char leafbuf[grouplen + 2]; char domainbuf[grouplen + 2]; nis_error status; nis_result *res; char *cp, *cp2; nis_object *obj; cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1)); cp = stpcpy (cp, ".groups_dir"); cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1); if (cp2 != NULL && cp2[0] != '\0') { *cp++ = '.'; stpcpy (cp, cp2); } else return NIS_BADNAME; obj = calloc (1, sizeof (nis_object)); if (__builtin_expect (obj == NULL, 0)) return NIS_NOMEMORY; obj->zo_oid.ctime = obj->zo_oid.mtime = time (NULL); obj->zo_name = strdup (leafbuf); obj->zo_owner = __nis_default_owner (NULL); obj->zo_group = __nis_default_group (NULL); obj->zo_domain = strdup (domainbuf); if (obj->zo_name == NULL || obj->zo_owner == NULL || obj->zo_group == NULL || obj->zo_domain == NULL) { free (obj->zo_group); free (obj->zo_owner); free (obj->zo_name); free (obj); return NIS_NOMEMORY; } obj->zo_access = __nis_default_access (NULL, 0); obj->zo_ttl = 60 * 60; obj->zo_data.zo_type = NIS_GROUP_OBJ; obj->zo_data.objdata_u.gr_data.gr_flags = flags; obj->zo_data.objdata_u.gr_data.gr_members.gr_members_len = 0; obj->zo_data.objdata_u.gr_data.gr_members.gr_members_val = NULL; res = nis_add (buf, obj); nis_free_object (obj); if (res == NULL) return NIS_NOMEMORY; status = NIS_RES_STATUS (res); nis_freeresult (res); return status; } return NIS_FAIL; }