diff options
Diffstat (limited to 'nis/nss_nisplus')
-rw-r--r-- | nis/nss_nisplus/nisplus-alias.c | 130 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-ethers.c | 148 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-grp.c | 243 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-hosts.c | 119 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-netgrp.c | 11 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-network.c | 268 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-parser.c | 337 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-proto.c | 226 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-publickey.c | 72 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-pwd.c | 197 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-rpc.c | 230 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-service.c | 253 | ||||
-rw-r--r-- | nis/nss_nisplus/nisplus-spwd.c | 154 |
13 files changed, 1370 insertions, 1018 deletions
diff --git a/nis/nss_nisplus/nisplus-alias.c b/nis/nss_nisplus/nisplus-alias.c index 1784778ca0..660ba3c34a 100644 --- a/nis/nss_nisplus/nisplus-alias.c +++ b/nis/nss_nisplus/nisplus-alias.c @@ -31,27 +31,47 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static u_long next_entry = 0; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) + { + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "mail_aliases.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; +} static int -_nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias, - char *buffer, size_t buflen) +_nss_nisplus_parse_aliasent (nis_result *result, unsigned long entry, + struct aliasent *alias, char *buffer, + size_t buflen) { if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_len != 1 || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (&result->objects.objects_val[entry]) != ENTRY_OBJ || + strcmp(result->objects.objects_val[entry].EN_data.en_type, "mail_aliases") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2) + result->objects.objects_val[entry].EN_data.en_cols.en_cols_len < 2) return 0; else { @@ -62,7 +82,7 @@ _nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias, char *line; char *cp; - if (NISENTRYLEN(0, 1, result) >= buflen) + if (NISENTRYLEN(entry, 1, result) >= buflen) { /* The line is too long for our buffer. */ no_more_room: @@ -71,19 +91,20 @@ _nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias, } else { - strncpy (buffer, NISENTRYVAL(0, 1, result), NISENTRYLEN(0, 1, result)); - buffer[NISENTRYLEN(0, 1, result)] = '\0'; + strncpy (buffer, NISENTRYVAL(entry, 1, result), + NISENTRYLEN(entry, 1, result)); + buffer[NISENTRYLEN(entry, 1, result)] = '\0'; } - if (NISENTRYLEN(0, 0, result) >= room_left) + if (NISENTRYLEN(entry, 0, result) >= room_left) goto no_more_room; alias->alias_local = 0; alias->alias_members_len = 0; *first_unused = '\0'; ++first_unused; - strcpy (first_unused, NISENTRYVAL(0, 0, result)); - first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + strcpy (first_unused, NISENTRYVAL(entry, 0, result)); + first_unused[NISENTRYLEN(entry, 0, result)] = '\0'; alias->alias_name = first_unused; /* Terminate the line for any case. */ @@ -129,23 +150,38 @@ _nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias, } } -enum nss_status -_nss_nisplus_setaliasent (void) +static enum nss_status +internal_setaliasent (void) { - __libc_lock_lock (lock); - if (result) nis_freeresult (result); result = NULL; - if (names) + + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + + next_entry = 0; + result = nis_list(tablename_val, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { - nis_freenames (names); - names = NULL; + nis_freeresult (result); + result = NULL; } + return niserr2nss (result->status); +} + +enum nss_status +_nss_nisplus_setaliasent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setaliasent (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -156,11 +192,7 @@ _nss_nisplus_endaliasent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + next_entry = 0; __libc_lock_unlock (lock); @@ -173,31 +205,18 @@ internal_nisplus_getaliasent_r (struct aliasent *alias, { int parse_res; + if (result == NULL) + internal_setaliasent (); + /* Get the next entry until we found a correct one. */ do { - if (result == NULL) - { - names = nis_getnames("mail_aliases.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; - - result = nis_first_entry(names[0]); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - return niserr2nss (result->status); - } - else - { - nis_result *res2; - - res2 = nis_next_entry(names[0], &result->cookie); - nis_freeresult (result); - result = res2; - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - return niserr2nss (result->status); - } + if (next_entry >= result->objects.objects_len) + return NSS_STATUS_NOTFOUND; - parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen); + parse_res = _nss_nisplus_parse_aliasent (result, next_entry, alias, + buffer, buflen); + ++next_entry; } while (!parse_res); return NSS_STATUS_SUCCESS; @@ -224,21 +243,26 @@ _nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL || strlen(name) > 8) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 30]; + char buf[strlen (name) + 30 + tablename_len]; - sprintf(buf, "[name=%s],mail_aliases.org_dir", name); + sprintf(buf, "[name=%s],%s", name, tablename_val); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); - parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen); + parse_res = _nss_nisplus_parse_aliasent (result, 0, alias, + buffer, buflen); if (parse_res) return NSS_STATUS_SUCCESS; diff --git a/nis/nss_nisplus/nisplus-ethers.c b/nis/nss_nisplus/nisplus-ethers.c index d83c7b2e11..7c07833ef4 100644 --- a/nis/nss_nisplus/nisplus-ethers.c +++ b/nis/nss_nisplus/nisplus-ethers.c @@ -33,7 +33,8 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; /* Because the `ethers' lookup does not fit so well in the scheme so we define a dummy struct here which helps us to use the available @@ -45,32 +46,6 @@ struct etherent }; struct etherent_data {}; -#define ENTNAME etherent -#define DATABASE "ethers" -#include "../../nss/nss_files/files-parse.c" -LINE_PARSER -("#", - /* Read the ethernet address: 6 x 8bit hexadecimal number. */ - { - size_t cnt; - - for (cnt = 0; cnt < 6; ++cnt) - { - unsigned int number; - - if (cnt < 5) - INT_FIELD (number, ISCOLON , 0, 16, (unsigned int)) - else - INT_FIELD (number, isspace, 0, 16, (unsigned int)) - - if (number > 0xff) - return 0; - result->e_addr.ether_addr_octet[cnt] = number; - } - }; - STRING_FIELD (result->e_name, isspace, 1); - ) - #define NISENTRYVAL(idx,col,res) \ ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) @@ -83,21 +58,18 @@ _nss_nisplus_parse_etherent (nis_result *result, struct etherent *ether, { char *p = buffer; size_t room_left = buflen; - struct parser_data *data = (void *) buffer; if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || result->objects.objects_len != 1 || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (NIS_RES_OBJECT (result)) != ENTRY_OBJ || + strcmp(NIS_RES_OBJECT (result)->EN_data.en_type, "ethers_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2) + NIS_RES_OBJECT(result)->EN_data.en_cols.en_cols_len < 2) return 0; - memset (p, '\0', room_left); - /* Generate the ether entry format and use the normal parser */ if (NISENTRYLEN (0, 0, result) +1 > room_left) { @@ -106,32 +78,47 @@ _nss_nisplus_parse_etherent (nis_result *result, struct etherent *ether, } strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); room_left -= (NISENTRYLEN (0, 0, result) +1); + ether->e_name = p; + + ether->e_addr = *ether_aton (NISENTRYVAL (0, 1, result)); + + return 1; +} - if (NISENTRYLEN (0, 1, result) +1 > room_left) +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) { - __set_errno (ERANGE); - return 0; - } - strcat (p, "\t"); - strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result)); - room_left -= (NISENTRYLEN (0, 1, result) + 1); + char buf [40 + strlen (nis_local_directory ())]; + char *p; - return _nss_files_parse_etherent (p,ether, data, buflen); + p = stpcpy (buf, "ethers.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; } + enum nss_status _nss_nisplus_setetherent (void) { + enum nss_status status; + + status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + status = NSS_STATUS_UNAVAIL; __libc_lock_unlock (lock); @@ -146,11 +133,6 @@ _nss_nisplus_endetherent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -163,16 +145,16 @@ internal_nisplus_getetherent_r (struct etherent *ether, char *buffer, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + /* Get the next entry until we found a correct one. */ do { if (result == NULL) { - names = nis_getnames("ethers.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; - - result = nis_first_entry(names[0]); + result = nis_first_entry(tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -180,7 +162,7 @@ internal_nisplus_getetherent_r (struct etherent *ether, char *buffer, { nis_result *res2; - res2 = nis_next_entry(names[0], &result->cookie); + res2 = nis_next_entry(tablename_val, &result->cookie); nis_freeresult (result); result = res2; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -214,16 +196,20 @@ _nss_nisplus_gethostton_r (const char *name, struct etherent *eth, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 255]; + char buf[strlen (name) + 40 + tablename_len]; - sprintf(buf, "[name=%s],ethers.org_dir", name); + sprintf(buf, "[name=%s],%s", name, tablename_val); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); @@ -245,34 +231,40 @@ _nss_nisplus_getntohost_r (const struct ether_addr *addr, struct etherent *eth, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[255]; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; if (addr == NULL) { __set_errno (EINVAL); return NSS_STATUS_UNAVAIL; } + else + { + int parse_res; + nis_result *result; + char buf[255 + tablename_len]; - memset (&buf, '\0', sizeof (buf)); - snprintf(buf, sizeof (buf), "[addr=%x:%x:%x:%x:%x:%x],ethers.org_dir", - addr->ether_addr_octet[0], addr->ether_addr_octet[1], - addr->ether_addr_octet[2], addr->ether_addr_octet[3], - addr->ether_addr_octet[4], addr->ether_addr_octet[5]); + memset (&buf, '\0', sizeof (buf)); + snprintf(buf, sizeof (buf), "[addr=%x:%x:%x:%x:%x:%x],ethers.org_dir", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - return niserr2nss (result->status); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); - parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen); + parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen); - if (parse_res) - return NSS_STATUS_SUCCESS; + if (parse_res) + return NSS_STATUS_SUCCESS; - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-grp.c b/nis/nss_nisplus/nisplus-grp.c index bf851e0cea..f759f61ca0 100644 --- a/nis/nss_nisplus/nisplus-grp.c +++ b/nis/nss_nisplus/nisplus-grp.c @@ -27,143 +27,66 @@ #include <rpcsvc/nislib.h> #include "nss-nisplus.h" +#include "nisplus-parser.h" __libc_lock_define_initialized (static, lock); static nis_result *result = NULL; -static nis_name *names = NULL; +static unsigned long next_entry = 0; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; -#define NISENTRYVAL(idx,col,res) \ -((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) - -#define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) - -int -_nss_nisplus_parse_grent (nis_result * result, struct group *gr, - char *buffer, size_t buflen) +static enum nss_status +_nss_create_tablename (void) { - char *first_unused = buffer; - size_t room_left = buflen; - char *line; - int count; - - if (result == NULL) - return 0; - - if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_len != 1 || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "group_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) - return 0; - - if (NISENTRYLEN (0, 0, result) >= room_left) + if (tablename_val == NULL) { - /* The line is too long for our buffer. */ - no_more_room: - __set_errno (ERANGE); - return 0; + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "group.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); } + return NSS_STATUS_SUCCESS; +} - strncpy (first_unused, NISENTRYVAL (0, 0, result), - NISENTRYLEN (0, 0, result)); - first_unused[NISENTRYLEN (0, 0, result)] = '\0'; - gr->gr_name = first_unused; - room_left -= (strlen (first_unused) + 1); - first_unused += strlen (first_unused) + 1; - - if (NISENTRYLEN (0, 1, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 1, result), - NISENTRYLEN (0, 1, result)); - first_unused[NISENTRYLEN (0, 1, result)] = '\0'; - gr->gr_passwd = first_unused; - room_left -= (strlen (first_unused) + 1); - first_unused += strlen (first_unused) + 1; - - if (NISENTRYLEN (0, 2, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 2, result), - NISENTRYLEN (0, 2, result)); - first_unused[NISENTRYLEN (0, 2, result)] = '\0'; - gr->gr_gid = atoi (first_unused); - room_left -= (strlen (first_unused) + 1); - first_unused += strlen (first_unused) + 1; - - if (NISENTRYLEN (0, 3, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 3, result), - NISENTRYLEN (0, 3, result)); - first_unused[NISENTRYLEN (0, 3, result)] = '\0'; - line = first_unused; - room_left -= (strlen (line) + 1); - first_unused += strlen (line) + 1; - /* Adjust the pointer so it is aligned for - storing pointers. */ - first_unused += __alignof__ (char *) - 1; - first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); - gr->gr_mem = (char **) first_unused; - - count = 0; - while (*line != '\0') - { - /* Skip leading blanks. */ - while (isspace (*line)) - ++line; - - if (*line == '\0') - break; - - if (room_left < sizeof (char *)) - goto no_more_room; - room_left -= sizeof (char *); - gr->gr_mem[count] = line; +static enum nss_status +internal_setgrent (void) +{ + if (result) + nis_freeresult (result); + result = NULL; + next_entry = 0; - while (*line != '\0' && *line != ',' && !isspace(*line)) - ++line; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - if (line != gr->gr_mem[count]) - { - if (*line != '\0') - { - *line = '\0'; - ++line; - } - ++count; - } - else - gr->gr_mem[count] = NULL; + result = nis_list (tablename_val, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + nis_freeresult (result); + result = NULL; } - if (room_left < sizeof (char *)) - goto no_more_room; - room_left -= sizeof (char *); - gr->gr_mem[count] = NULL; - - return 1; + return niserr2nss (result->status); } enum nss_status _nss_nisplus_setgrent (void) { + enum nss_status status; + __libc_lock_lock (lock); - if (result) - nis_freeresult (result); - result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + status = internal_setgrent (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -174,11 +97,6 @@ _nss_nisplus_endgrent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -190,31 +108,18 @@ internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen) { int parse_res; + if (result == NULL) + internal_setgrent (); + /* Get the next entry until we found a correct one. */ do { - if (result == NULL) - { - names = nis_getnames ("group.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; - - result = nis_first_entry (names[0]); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - return niserr2nss (result->status); - } - else - { - nis_result *res; - - res = nis_next_entry (names[0], &result->cookie); - nis_freeresult (result); - result = res; - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - return niserr2nss (result->status); - } + if (next_entry >= result->objects.objects_len) + return NSS_STATUS_NOTFOUND; - parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + parse_res = _nss_nisplus_parse_grent (result, next_entry, gr, + buffer, buflen); + ++next_entry; } while (!parse_res); @@ -241,16 +146,20 @@ _nss_nisplus_getgrnam_r (const char *name, struct group *gr, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL || strlen (name) > 8) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 24]; + char buf[strlen (name) + 24 + tablename_len]; - sprintf (buf, "[name=%s],group.org_dir", name); + sprintf (buf, "[name=%s],%s", name, tablename_val); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { @@ -260,7 +169,7 @@ _nss_nisplus_getgrnam_r (const char *name, struct group *gr, return status; } - parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen); nis_freeresult (result); @@ -278,31 +187,37 @@ enum nss_status _nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[36]; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - sprintf (buf, "[gid=%d],group.org_dir", gid); + { + int parse_res; + nis_result *result; + char buf[36 + tablename_len]; - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + sprintf (buf, "[gid=%d],%s", gid, tablename_val); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (result->status); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); - nis_freeresult (result); - return status; - } + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } - parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + parse_res = _nss_nisplus_parse_grent (result, 0, gr, buffer, buflen); - nis_freeresult (result); + nis_freeresult (result); - if (parse_res) - return NSS_STATUS_SUCCESS; + if (parse_res) + return NSS_STATUS_SUCCESS; - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-hosts.c b/nis/nss_nisplus/nisplus-hosts.c index ee87a78225..19f9161076 100644 --- a/nis/nss_nisplus/nisplus-hosts.c +++ b/nis/nss_nisplus/nisplus-hosts.c @@ -33,13 +33,14 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) /* Get implementation for some internal functions. */ #include "../../resolv/mapv4v6addr.h" @@ -57,10 +58,10 @@ _nss_nisplus_parse_hostent (nis_result *result, int af, struct hostent *host, return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "hosts_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].EN_data.en_type, + "hosts_tbl") != 0 || + result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 4) return 0; if (room_left < NISENTRYLEN (0, 2, result) + 1) @@ -162,37 +163,58 @@ _nss_nisplus_parse_hostent (nis_result *result, int af, struct hostent *host, host->h_aliases[i] = line; while (*line != '\0' && *line != ' ') - line++; + ++line; - if (line != host->h_aliases[i]) - { - *line = '\0'; - line++; - i++; - } + if (*line == ' ') + { + *line = '\0'; + ++line; + ++i; + } + else + host->h_aliases[i+1] = NULL; } return 1; } +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) + { + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "hosts.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; +} + enum nss_status _nss_nisplus_sethostent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + status = NSS_STATUS_UNAVAIL; __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -203,11 +225,6 @@ _nss_nisplus_endhostent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -225,11 +242,11 @@ internal_nisplus_gethostent_r (struct hostent *host, char *buffer, { if (result == NULL) { - names = nis_getnames("hosts.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry(names[0]); + result = nis_first_entry(tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { int retval; @@ -248,7 +265,7 @@ internal_nisplus_gethostent_r (struct hostent *host, char *buffer, { nis_result *res2; - res2 = nis_next_entry(names[0], &result->cookie); + res2 = nis_next_entry(tablename_val, &result->cookie); nis_freeresult (result); result = res2; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -302,6 +319,13 @@ _nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host, { int parse_res, retval; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + { + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + if (name == NULL) { __set_errno (EINVAL); @@ -311,28 +335,27 @@ _nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host, else { nis_result *result; - char buf[strlen (name) + 255]; + char buf[strlen (name) + 255 + tablename_len]; /* Search at first in the alias list, and use the correct name for the next search */ - sprintf(buf, "[name=%s],hosts.org_dir", name); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + sprintf(buf, "[name=%s],%s", name, tablename_val); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); /* If we do not find it, try it as original name. But if the database is correct, we should find it in the first case, too */ - if ((result->status != NIS_SUCCESS && - result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val->EN_data.en_type, "hosts_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len - < 3) - sprintf(buf, "[cname=%s],hosts.org_dir", name); + result->objects.objects_val->EN_data.en_cols.en_cols_len < 3) + sprintf(buf, "[cname=%s],%s", name, tablename_val); else - sprintf(buf, "[cname=%s],hosts.org_dir", NISENTRYVAL(0, 0, result)); + sprintf(buf, "[cname=%s],%s", NISENTRYVAL(0, 0, result), + tablename_val); nis_freeresult (result); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); retval = niserr2nss (result->status); if (retval != NSS_STATUS_SUCCESS) @@ -385,17 +408,21 @@ _nss_nisplus_gethostbyaddr_r (const char *addr, int addrlen, int type, struct hostent *host, char *buffer, size_t buflen, int *herrnop) { + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (addr == NULL) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[1025]; + char buf[255 + tablename_len]; int retval, parse_res; - snprintf(buf, sizeof (buf) -1, "[addr=%s],hosts.org_dir", - inet_ntoa (*(struct in_addr *)addr)); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + snprintf(buf, sizeof (buf) -1, "[addr=%s],%s", + inet_ntoa (*(struct in_addr *)addr), tablename_val); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); retval = niserr2nss (result->status); if (retval != NSS_STATUS_SUCCESS) diff --git a/nis/nss_nisplus/nisplus-netgrp.c b/nis/nss_nisplus/nisplus-netgrp.c index 5907882725..670d0bb4ed 100644 --- a/nis/nss_nisplus/nisplus-netgrp.c +++ b/nis/nss_nisplus/nisplus-netgrp.c @@ -36,10 +36,10 @@ static unsigned long data_size = 0; static unsigned long position = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) static enum nss_status _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer, @@ -49,8 +49,7 @@ _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer, /* Some sanity checks. */ if (data == NULL || data_size == 0) - /* User bug. setnetgrent() wasn't called before. */ - abort (); + return NSS_STATUS_NOTFOUND; if (position == data_size) return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; @@ -154,9 +153,9 @@ _nss_nisplus_setnetgrent (char *group) position = 0; } - sprintf(buf, "[name=%s],netgroup.org_dir", group); + sprintf (buf, "[name=%s],netgroup.org_dir", group); - data = nis_list(buf, EXPAND_NAME, NULL, NULL); + data = nis_list (buf, EXPAND_NAME, NULL, NULL); if (niserr2nss (data->status) != NSS_STATUS_SUCCESS) { diff --git a/nis/nss_nisplus/nisplus-network.c b/nis/nss_nisplus/nisplus-network.c index 8d6e08b2c6..9a46397149 100644 --- a/nis/nss_nisplus/nisplus-network.c +++ b/nis/nss_nisplus/nisplus-network.c @@ -29,109 +29,160 @@ #include "nss-nisplus.h" -/* Get the declaration of the parser function. */ -#define ENTNAME netent -#define DATABASE "networks" -#define TRAILING_LIST_MEMBER n_aliases -#define TRAILING_LIST_SEPARATOR_P isspace -#include "../nss/nss_files/files-parse.c" -LINE_PARSER -("#", - { - char *addr; - - STRING_FIELD (result->n_name, isspace, 1); - - STRING_FIELD (addr, isspace, 1); - result->n_net = inet_network (addr); - - }) - __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) static int _nss_nisplus_parse_netent (nis_result *result, struct netent *network, char *buffer, size_t buflen) { - char *p = buffer; + char *first_unused = buffer; size_t room_left = buflen; unsigned int i; - struct parser_data *data = (void *) buffer; + char *p, *line; if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].EN_data.en_type, "networks_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3) return 0; - /* Generate the network entry format and use the normal parser */ - if (NISENTRYLEN (0, 0, result) +1 > room_left) + if (NISENTRYLEN(0, 0, result) >= room_left) { + /* The line is too long for our buffer. */ + no_more_room: __set_errno (ERANGE); return 0; } - memset (p, '\0', room_left); + strncpy (first_unused, NISENTRYVAL(0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + network->n_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + network->n_addrtype = 0; + network->n_net = inet_network (NISENTRYVAL (0, 2, result)); + p = first_unused; + + line = p; + for (i = 0; i < result->objects.objects_len; i++) + { + if (strcmp (NISENTRYVAL (i, 1, result), network->n_name) != 0) + { + if (NISENTRYLEN (i, 1, result) + 2 > room_left) + { + __set_errno (ERANGE); + return 0; + } + p = stpcpy(p, " "); + p = stpncpy (p, NISENTRYVAL (i, 1, result), + NISENTRYLEN (i, 1, result)); + *p = '\0'; + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + } + ++p; + first_unused = p; + + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + network->n_aliases = (char **) first_unused; + if (room_left < 2 * sizeof (char *)) + goto no_more_room; + room_left -= (2 * sizeof (char *)); + network->n_aliases[0] = NULL; + + i = 0; + while (*line != '\0') + { + /* Skip leading blanks. */ + while (isspace (*line)) + line++; - strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); - room_left -= (NISENTRYLEN (0, 0, result) +1); + if (*line == '\0') + break; - if (NISENTRYLEN (0, 2, result) +1 > room_left) - { - __set_errno (ERANGE); - return 0; + if (room_left < sizeof (char *)) + { + __set_errno (ERANGE); + return 0; + } + + room_left -= sizeof (char *); + network->n_aliases[i] = line; + + while (*line != '\0' && *line != ' ') + ++line; + + if (line != network->n_aliases[i]) + { + if (*line != '\0') + { + *line = '\0'; + ++line; + } + ++i; + } + else + network->n_aliases[i] = NULL; } - strcat (p, "\t"); - strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); - room_left -= (NISENTRYLEN (0, 2, result) + 1); - /* + 1: We overwrite the last \0 */ - for (i = 1; i < result->objects.objects_len; i++) + return 1; +} + +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) { - if (NISENTRYLEN (i, 1, result) +1 > room_left) - { - __set_errno (ERANGE); - return 0; - } - strcat (p, " "); - strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); - room_left -= (NISENTRYLEN (i, 1, result) + 1); + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "networks.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); } - - return _nss_files_parse_netent (p, network, data, buflen); + return NSS_STATUS_SUCCESS; } enum nss_status _nss_nisplus_setnetent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + status = NSS_STATUS_UNAVAIL; __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -142,11 +193,6 @@ _nss_nisplus_endnetent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -164,11 +210,11 @@ internal_nisplus_getnetent_r (struct netent *network, char *buffer, { if (result == NULL) { - names = nis_getnames("networks.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry(names[0]); + result = nis_first_entry(tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { int retval; @@ -178,15 +224,17 @@ internal_nisplus_getnetent_r (struct netent *network, char *buffer, { *herrnop = NETDB_INTERNAL; __set_errno (EAGAIN); + return retval; } - return retval; + else + return retval; } } else { nis_result *res; - res = nis_next_entry(names[0], &result->cookie); + res = nis_next_entry(tablename_val, &result->cookie); nis_freeresult (result); result = res; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -236,6 +284,10 @@ _nss_nisplus_getnetbyname_r (const char *name, struct netent *network, { int parse_res, retval; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL) { __set_errno (EINVAL); @@ -245,28 +297,28 @@ _nss_nisplus_getnetbyname_r (const char *name, struct netent *network, else { nis_result *result; - char buf[strlen (name) + 255]; - + char buf[strlen (name) + 255 + tablename_len]; /* Search at first in the alias list, and use the correct name for the next search */ - sprintf(buf, "[name=%s],networks.org_dir", name); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + sprintf(buf, "[name=%s],%s", name, tablename_val); + result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); /* If we do not find it, try it as original name. But if the database is correct, we should find it in the first case, too */ if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].EN_data.en_type, "networks_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) - sprintf(buf, "[cname=%s],networks.org_dir", name); + result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3) + sprintf(buf, "[cname=%s],%s", name, tablename_val); else - sprintf(buf, "[cname=%s],networks.org_dir", NISENTRYVAL(0, 0, result)); + sprintf(buf, "[cname=%s],%s", NISENTRYVAL(0, 0, result), + tablename_val); nis_freeresult (result); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); retval = niserr2nss (result->status); if (retval != NSS_STATUS_SUCCESS) @@ -301,39 +353,45 @@ _nss_nisplus_getnetbyaddr_r (const unsigned long addr, const int type, struct netent *network, char *buffer, size_t buflen, int *herrnop) { - int parse_res, retval; - nis_result *result; - char buf[1024]; - struct in_addr in; + if (tablename_val == NULL) + if (_nss_create_tablename() != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - in = inet_makeaddr (addr, 0); - snprintf(buf, sizeof (buf) - 1, "[addr=%s],networks.org_dir", - inet_ntoa (in)); + { + int parse_res, retval; + nis_result *result; + char buf[1024 + tablename_len]; + struct in_addr in; - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + in = inet_makeaddr (addr, 0); + snprintf(buf, sizeof (buf) - 1, "[addr=%s],%s", + inet_ntoa (in), tablename_len); - retval = niserr2nss (result->status); - if (retval != NSS_STATUS_SUCCESS) - { - if (retval == NSS_STATUS_TRYAGAIN) - { - __set_errno (EAGAIN); - *herrnop = NETDB_INTERNAL; - } - nis_freeresult (result); - return retval; - } + result = nis_list(buf, EXPAND_NAME, NULL, NULL); - parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen); + retval = niserr2nss (result->status); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + nis_freeresult (result); + return retval; + } - nis_freeresult (result); + parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen); - if (parse_res) - return NSS_STATUS_SUCCESS; + nis_freeresult (result); - *herrnop = NETDB_INTERNAL; - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + if (parse_res) + return NSS_STATUS_SUCCESS; + + *herrnop = NETDB_INTERNAL; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-parser.c b/nis/nss_nisplus/nisplus-parser.c new file mode 100644 index 0000000000..bb6bba1e3e --- /dev/null +++ b/nis/nss_nisplus/nisplus-parser.c @@ -0,0 +1,337 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pwd.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <rpcsvc/nis.h> + +#include "nisplus-parser.h" + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + + +int +_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, + char *buffer, size_t buflen) +{ + char *first_unused = buffer; + size_t room_left = buflen; + + if (result == NULL) + return 0; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val->EN_data.en_type, + "passwd_tbl") != 0 || + result->objects.objects_val->EN_data.en_cols.en_cols_len < 7) + return 0; + + if (NISENTRYLEN (0, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return 0; + } + + strncpy (first_unused, NISENTRYVAL(0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + pw->pw_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 1, result), + NISENTRYLEN (0, 1, result)); + first_unused[NISENTRYLEN(0, 1, result)] = '\0'; + pw->pw_passwd = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 2, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 2, result), + NISENTRYLEN (0, 2, result)); + first_unused[NISENTRYLEN(0, 2, result)] = '\0'; + pw->pw_uid = atoi (first_unused); + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 3, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 3, result), + NISENTRYLEN (0, 3, result)); + first_unused[NISENTRYLEN(0, 3, result)] = '\0'; + pw->pw_gid = atoi (first_unused); + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 4, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 4, result), + NISENTRYLEN (0, 4, result)); + first_unused[NISENTRYLEN(0, 4, result)] = '\0'; + pw->pw_gecos = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 5, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 5, result), + NISENTRYLEN (0, 5, result)); + first_unused[NISENTRYLEN(0, 5, result)] = '\0'; + pw->pw_dir = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 6, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 6, result), + NISENTRYLEN (0, 6, result)); + first_unused[NISENTRYLEN (0, 6, result)] = '\0'; + pw->pw_shell = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + return 1; +} + +int +_nss_nisplus_parse_grent (nis_result *result, u_long entry, + struct group *gr, char *buffer, size_t buflen) +{ + char *first_unused = buffer; + size_t room_left = buflen; + char *line; + int count; + + if (result == NULL) + return 0; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + __type_of(result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val[entry].EN_data.en_type, + "group_tbl") != 0 || + result->objects.objects_val[entry].EN_data.en_cols.en_cols_len < 4) + return 0; + + if (NISENTRYLEN (entry, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return 0; + } + + strncpy (first_unused, NISENTRYVAL (entry, 0, result), + NISENTRYLEN (entry, 0, result)); + first_unused[NISENTRYLEN (entry, 0, result)] = '\0'; + gr->gr_name = first_unused; + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (entry, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (entry, 1, result), + NISENTRYLEN (entry, 1, result)); + first_unused[NISENTRYLEN (entry, 1, result)] = '\0'; + gr->gr_passwd = first_unused; + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (entry, 2, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (entry, 2, result), + NISENTRYLEN (entry, 2, result)); + first_unused[NISENTRYLEN (entry, 2, result)] = '\0'; + gr->gr_gid = atoi (first_unused); + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (entry, 3, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (entry, 3, result), + NISENTRYLEN (entry, 3, result)); + first_unused[NISENTRYLEN (entry, 3, result)] = '\0'; + line = first_unused; + room_left -= (strlen (line) + 1); + first_unused += strlen (line) + 1; + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + gr->gr_mem = (char **) first_unused; + + count = 0; + while (*line != '\0') + { + /* Skip leading blanks. */ + while (isspace (*line)) + ++line; + + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + gr->gr_mem[count] = line; + + while (*line != '\0' && *line != ',' && !isspace(*line)) + ++line; + + if (line != gr->gr_mem[count]) + { + if (*line != '\0') + { + *line = '\0'; + ++line; + } + ++count; + } + else + gr->gr_mem[count] = NULL; + } + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + gr->gr_mem[count] = NULL; + + return 1; +} + +int +_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp, + char *buffer, size_t buflen) +{ + char *first_unused = buffer; + size_t room_left = buflen; + + if (result == NULL) + return 0; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + __type_of(result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val->EN_data.en_type, + "passwd_tbl") != 0 || + result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 8) + return 0; + + if (NISENTRYLEN(0, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return 0; + } + + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + sp->sp_namp = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 1, result), + NISENTRYLEN (0, 1, result)); + first_unused[NISENTRYLEN(0, 1, result)] = '\0'; + sp->sp_pwdp = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact = + sp->sp_expire = sp->sp_flag = -1; + + if (NISENTRYLEN (0, 7, result) > 0) + { + char *line, *cp; + + line = NISENTRYVAL (0, 7, result); + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_lstchg = atol (line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_min = atol(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_max = atol(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_warn = atol(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_inact = atol(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_expire = atol(line); + + line = cp; + if (line == NULL) + return 0; + sp->sp_flag = atol(line); + } + + return 1; +} diff --git a/nis/nss_nisplus/nisplus-proto.c b/nis/nss_nisplus/nisplus-proto.c index ee0341d0b9..1ee9a8944b 100644 --- a/nis/nss_nisplus/nisplus-proto.c +++ b/nis/nss_nisplus/nisplus-proto.c @@ -31,97 +31,146 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; - -#define ENTNAME protoent -#define DATABASE "protocols" -#define TRAILING_LIST_MEMBER p_aliases -#define TRAILING_LIST_SEPARATOR_P isspace -#include "../../nss/nss_files/files-parse.c" -LINE_PARSER -("#", - STRING_FIELD (result->p_name, isspace, 1); - INT_FIELD (result->p_proto, isspace, 1, 10,); -) +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) static int _nss_nisplus_parse_protoent (nis_result * result, struct protoent *proto, char *buffer, size_t buflen) { - char *p = buffer; + char *first_unused = buffer; size_t room_left = buflen; unsigned int i; - struct parser_data *data = (void *) buffer; + char *p, *line; if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "protocols_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + __type_of (NIS_RES_OBJECT (result)) != ENTRY_OBJ || + strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "protocols_tbl") != 0 + || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 3) return 0; - memset (p, '\0', room_left); - /* Generate the protocols entry format and use the normal parser */ if (NISENTRYLEN (0, 0, result) + 1 > room_left) { + no_more_room: __set_errno (ERANGE); return 0; } - strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); - room_left -= (NISENTRYLEN (0, 0, result) + 1); + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN (0, 0, result)] = '\0'; + proto->p_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + if (NISENTRYLEN (0, 2, result) + 1 > room_left) + goto no_more_room; + proto->p_proto = atoi (NISENTRYVAL (0, 2, result)); + p = first_unused; + + line = p; + for (i = 0; i < result->objects.objects_len; i++) { - __set_errno (ERANGE); - return 0; + if (strcmp (NISENTRYVAL (i, 1, result), proto->p_name) != 0) + { + if (NISENTRYLEN (i, 1, result) + 2 > room_left) + goto no_more_room; + p = stpcpy(p, " "); + p = stpncpy (p, NISENTRYVAL (i, 1, result), + NISENTRYLEN (i, 1, result)); + *p = '\0'; + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } } - strcat (p, "\t"); - strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); - room_left -= (NISENTRYLEN (0, 2, result) + 1); - /* + 1: We overwrite the last \0 */ - - for (i = 1; i < result->objects.objects_len; i++) + ++p; + first_unused = p; + + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + proto->p_aliases = (char **) first_unused; + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= (sizeof (char *)); + proto->p_aliases[0] = NULL; + + i = 0; + while (*line != '\0') { - if (NISENTRYLEN (i, 1, result) + 1 > room_left) - { - __set_errno (ERANGE); - return 0; - } - strcat (p, " "); - strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); - room_left -= (NISENTRYLEN (i, 1, result) + 1); + /* Skip leading blanks. */ + while (isspace (*line)) + line++; + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + + room_left -= sizeof (char *); + proto->p_aliases[i] = line; + + while (*line != '\0' && *line != ' ') + ++line; + + if (*line == ' ') + { + *line = '\0'; + ++line; + ++i; + } + else + proto->p_aliases[i+1] = NULL; } - return _nss_files_parse_protoent (p, proto, data, buflen); + return 1; +} + +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) + { + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "protocols.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; } enum nss_status _nss_nisplus_setprotoent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + status = _nss_create_tablename (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -132,11 +181,6 @@ _nss_nisplus_endprotoent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -154,11 +198,11 @@ internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer, { if (result == NULL) { - names = nis_getnames ("protocols.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry (names[0]); + result = nis_first_entry (tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -166,7 +210,7 @@ internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer, { nis_result *res; - res = nis_next_entry (names[0], &result->cookie); + res = nis_next_entry (tablename_val, &result->cookie); nis_freeresult (result); result = res; @@ -202,32 +246,37 @@ _nss_nisplus_getprotobyname_r (const char *name, struct protoent *proto, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 255]; + char buf[strlen (name) + 255 + tablename_len]; /* Search at first in the alias list, and use the correct name for the next search */ - sprintf (buf, "[name=%s],protocols.org_dir", name); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + sprintf (buf, "[name=%s],%s", name, tablename_val); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); /* If we do not find it, try it as original name. But if the database is correct, we should find it in the first case, too */ if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val->EN_data.en_type, "protocols_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) - sprintf (buf, "[cname=%s],protocols.org_dir", name); + result->objects.objects_val->EN_data.en_cols.en_cols_len < 3) + sprintf (buf, "[cname=%s],%s", name, tablename_val); else - sprintf (buf, "[cname=%s],protocols.org_dir", NISENTRYVAL (0, 0, result)); + sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result), + tablename_val); nis_freeresult (result); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { @@ -255,30 +304,35 @@ enum nss_status _nss_nisplus_getprotobynumber_r (const int number, struct protoent *proto, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[46]; - - snprintf (buf, sizeof (buf), "[number=%d],protocols.org_dir", number); + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + { + int parse_res; + nis_result *result; + char buf[46 + tablename_len]; - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (result->status); + result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); - nis_freeresult (result); - return status; - } + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); - parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen); + nis_freeresult (result); + return status; + } - nis_freeresult (result); - if (parse_res) - return NSS_STATUS_SUCCESS; + parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen); - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + nis_freeresult (result); + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-publickey.c b/nis/nss_nisplus/nisplus-publickey.c index 91cfba730e..4c596b8ada 100644 --- a/nis/nss_nisplus/nisplus-publickey.c +++ b/nis/nss_nisplus/nisplus-publickey.c @@ -61,10 +61,10 @@ _nss_nisplus_getpublickey (const char *netname, char *pkey) netname, domain); if (buf[strlen (buf)-1] != '.') - strcat(buf, "."); + strcat (buf, "."); - res = nis_list(buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, - NULL, NULL); + res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); retval = niserr2nss (res->status); @@ -192,7 +192,7 @@ parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist) return NSS_STATUS_NOTFOUND; } - *gidp = (atoi (s)); + *gidp = atoi (s); gidlen = 0; @@ -238,7 +238,7 @@ _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, /* XXX but we cant, for now. XXX */ res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, NULL, NULL); - switch(res->status) + switch (res->status) { case NIS_SUCCESS: case NIS_S_SUCCESS: @@ -274,10 +274,10 @@ _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, netname, domain); } - len = ENTRY_LEN(res->objects.objects_val, 0); - strncpy(principal, ENTRY_VAL(res->objects.objects_val, 0), len); + len = ENTRY_LEN (res->objects.objects_val, 0); + strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len); principal[len] = '\0'; - nis_freeresult(res); + nis_freeresult (res); if (principal[0] == '\0') return NSS_STATUS_UNAVAIL; @@ -287,45 +287,45 @@ _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, * LOCAL entry in **local** cred table. */ domain = nis_local_directory (); - if ((strlen(principal)+strlen(domain)+45) > + if ((strlen (principal)+strlen (domain)+45) > (size_t) NIS_MAXNAMELEN) { syslog (LOG_ERR, _("netname2user: principal name '%s' too long"), principal); return NSS_STATUS_UNAVAIL; } - sprintf(sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s", + sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s", principal, domain); if (sname[strlen(sname) - 1] != '.') strcat(sname, "."); /* must use authenticated call here */ /* XXX but we cant, for now. XXX */ - res = nis_list(sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, - NULL, NULL); - switch(res->status) { - case NIS_NOTFOUND: - case NIS_PARTIAL: - case NIS_NOSUCHNAME: - case NIS_NOSUCHTABLE: - nis_freeresult (res); - return NSS_STATUS_NOTFOUND; - case NIS_S_NOTFOUND: - case NIS_TRYAGAIN: - syslog (LOG_ERR, - "netname2user: (nis+ lookup): %s\n", - nis_sperrno (res->status)); - nis_freeresult (res); - return NSS_STATUS_TRYAGAIN; - case NIS_SUCCESS: - case NIS_S_SUCCESS: - break; /* go and do something useful */ - default: - syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", - nis_sperrno (res->status)); - nis_freeresult (res); - return NSS_STATUS_UNAVAIL; - } + res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); + switch(res->status) + { + case NIS_NOTFOUND: + case NIS_PARTIAL: + case NIS_NOSUCHNAME: + case NIS_NOSUCHTABLE: + nis_freeresult (res); + return NSS_STATUS_NOTFOUND; + case NIS_S_NOTFOUND: + case NIS_TRYAGAIN: + syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_TRYAGAIN; + case NIS_SUCCESS: + case NIS_S_SUCCESS: + break; /* go and do something useful */ + default: + syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_UNAVAIL; + } if (res->objects.objects_len > 1) { @@ -339,7 +339,7 @@ _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, netname, domain); } /* Fetch the uid */ - *uidp = (atoi (ENTRY_VAL (res->objects.objects_val, 2))); + *uidp = atoi (ENTRY_VAL (res->objects.objects_val, 2)); if (*uidp == 0) { diff --git a/nis/nss_nisplus/nisplus-pwd.c b/nis/nss_nisplus/nisplus-pwd.c index 89b0eff7a7..459a1a4380 100644 --- a/nis/nss_nisplus/nisplus-pwd.c +++ b/nis/nss_nisplus/nisplus-pwd.c @@ -30,127 +30,48 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; -#define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) +extern int _nss_nisplus_parse_pwent (nis_result *res, struct passwd *pw, + char *buffer, size_t buflen); -#define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) - -int -_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, - char *buffer, size_t buflen) +static enum nss_status +_nss_create_tablename (void) { - char *first_unused = buffer; - size_t room_left = buflen; - - if (result == NULL) - return 0; - - if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_len != 1 || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "passwd_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 7) - return 0; - - if (NISENTRYLEN(0, 0, result) >= room_left) + if (tablename_val == NULL) { - /* The line is too long for our buffer. */ - no_more_room: - __set_errno (ERANGE); - return 0; + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "passwd.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); } - - strncpy (first_unused, NISENTRYVAL(0, 0, result), - NISENTRYLEN (0, 0, result)); - first_unused[NISENTRYLEN(0, 0, result)] = '\0'; - pw->pw_name = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 1, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL(0, 1, result), - NISENTRYLEN (0, 1, result)); - first_unused[NISENTRYLEN(0, 1, result)] = '\0'; - pw->pw_passwd = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 2, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 2, result), - NISENTRYLEN (0, 2, result)); - first_unused[NISENTRYLEN(0, 2, result)] = '\0'; - pw->pw_uid = atoi (first_unused); - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 3, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL(0, 3, result), - NISENTRYLEN (0, 3, result)); - first_unused[NISENTRYLEN(0, 3, result)] = '\0'; - pw->pw_gid = atoi (first_unused); - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 4, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL(0, 4, result), - NISENTRYLEN (0, 4, result)); - first_unused[NISENTRYLEN(0, 4, result)] = '\0'; - pw->pw_gecos = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 5, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 5, result), - NISENTRYLEN (0, 5, result)); - first_unused[NISENTRYLEN(0, 5, result)] = '\0'; - pw->pw_dir = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 6, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 6, result), - NISENTRYLEN (0, 6, result)); - first_unused[NISENTRYLEN (0, 6, result)] = '\0'; - pw->pw_shell = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - return 1; + return NSS_STATUS_SUCCESS; } + enum nss_status _nss_nisplus_setpwent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + status = _nss_create_tablename (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -161,11 +82,6 @@ _nss_nisplus_endpwent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -182,11 +98,11 @@ internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen) { if (result == NULL) { - names = nis_getnames ("passwd.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry(names[0]); + result = nis_first_entry(tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -194,7 +110,7 @@ internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen) { nis_result *res; - res = nis_next_entry(names[0], &result->cookie); + res = nis_next_entry(tablename_val, &result->cookie); nis_freeresult (result); result = res; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -227,16 +143,20 @@ _nss_nisplus_getpwnam_r (const char *name, struct passwd *pw, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL || strlen (name) > 8) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 24]; + char buf[strlen (name) + 24 + tablename_len]; - sprintf(buf, "[name=%s],passwd.org_dir", name); + sprintf(buf, "[name=%s],%s", name, tablename_val); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { @@ -264,30 +184,35 @@ enum nss_status _nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[100]; - - sprintf(buf, "[uid=%d],passwd.org_dir", uid); + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + { + int parse_res; + nis_result *result; + char buf[100 + tablename_len]; - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + sprintf(buf, "[uid=%d],%s", uid, tablename_val); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (result->status); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); - nis_freeresult (result); - return status; - } + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); - parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen); + nis_freeresult (result); + return status; + } - nis_freeresult (result); - if (parse_res) - return NSS_STATUS_SUCCESS; + parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen); - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + nis_freeresult (result); + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-rpc.c b/nis/nss_nisplus/nisplus-rpc.c index 180e9169f2..cebd5d7183 100644 --- a/nis/nss_nisplus/nisplus-rpc.c +++ b/nis/nss_nisplus/nisplus-rpc.c @@ -31,98 +31,148 @@ __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; - -#define ENTNAME rpcent -#define DATABASE "rpc" -#define TRAILING_LIST_MEMBER r_aliases -#define TRAILING_LIST_SEPARATOR_P isspace -#include "../../nss/nss_files/files-parse.c" -LINE_PARSER -("#", - STRING_FIELD (result->r_name, isspace, 1); - INT_FIELD (result->r_number, isspace, 1, 10,); - ) +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) static int _nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc, char *buffer, size_t buflen) { - char *p = buffer; + char *first_unused = buffer; size_t room_left = buflen; unsigned int i; - struct parser_data *data = (void *) buffer; + char *p, *line; + if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].EN_data.en_type, "rpc_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3) return 0; - memset (p, '\0', room_left); - - /* Generate the rpc entry format and use the normal parser */ - if (NISENTRYLEN (0, 0, result) +1 > room_left) + if (NISENTRYLEN (0, 0, result) >= room_left) { + no_more_room: __set_errno (ERANGE); return 0; } - strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); - room_left -= (NISENTRYLEN (0, 0, result) +1); - - if (NISENTRYLEN (0, 2, result) +1 > room_left) + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN (0, 0, result)] = '\0'; + rpc->r_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + rpc->r_number = atoi (NISENTRYVAL (0, 2, result)); + p = first_unused; + + line = p; + for (i = 0; i < result->objects.objects_len; i++) { - __set_errno (ERANGE); - return 0; + if (strcmp (NISENTRYVAL (i, 1, result), rpc->r_name) != 0) + { + if (NISENTRYLEN (i, 1, result) + 2 > room_left) + goto no_more_room; + p = stpcpy(p, " "); + p = stpncpy (p, NISENTRYVAL (i, 1, result), + NISENTRYLEN (i, 1, result)); + *p = '\0'; + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } } - strcat (p, "\t"); - strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); - room_left -= (NISENTRYLEN (0, 2, result) + 1); - /* + 1: We overwrite the last \0 */ - - for (i = 0; i < result->objects.objects_len; i++) - /* XXX should we start with i = 0 or with i = 1 ? */ + ++p; + first_unused = p; + + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + rpc->r_aliases = (char **) first_unused; + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= (sizeof (char *)); + rpc->r_aliases[0] = NULL; + + i = 0; + while (*line != '\0') { - if (NISENTRYLEN (i, 1, result) +1 > room_left) + /* Skip leading blanks. */ + while (isspace (*line)) + line++; + + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + + room_left -= sizeof (char *); + rpc->r_aliases[i] = line; + + while (*line != '\0' && *line != ' ') + ++line; + + if (line != rpc->r_aliases[i]) { - __set_errno (ERANGE); - return 0; + if (*line != '\0') + { + *line = '\0'; + ++line; + } + ++i; } - strcat (p, " "); - strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); - room_left -= (NISENTRYLEN (i, 1, result) + 1); + else + rpc->r_aliases[i] = NULL; } - return _nss_files_parse_rpcent (p, rpc, data, buflen); + return 1; } +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) + { + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "rpc.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; +} + + enum nss_status _nss_nisplus_setrpcent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + status = _nss_create_tablename (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -133,11 +183,6 @@ _nss_nisplus_endrpcent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -155,11 +200,11 @@ internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer, { if (result == NULL) { - names = nis_getnames ("rpc.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry(names[0]); + result = nis_first_entry(tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -167,7 +212,7 @@ internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer, { nis_result *res; - res = nis_next_entry (names[0], &result->cookie); + res = nis_next_entry (tablename_val, &result->cookie); nis_freeresult (result); result = res; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -201,32 +246,37 @@ _nss_nisplus_getrpcbyname_r (const char *name, struct rpcent *rpc, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 255]; + char buf[strlen (name) + 255 + tablename_len]; /* Search at first in the alias list, and use the correct name for the next search */ - sprintf (buf, "[name=%s],rpc.org_dir", name); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + sprintf (buf, "[name=%s],%s", name, tablename_val); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); /* If we do not find it, try it as original name. But if the database is correct, we should find it in the first case, too */ if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val->EN_data.en_type, "rpc_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) - sprintf (buf, "[cname=%s],rpc.org_dir", name); + result->objects.objects_val->EN_data.en_cols.en_cols_len < 3) + sprintf (buf, "[cname=%s],%s", name, tablename_val); else - sprintf (buf, "[cname=%s],rpc.org_dir", NISENTRYVAL(0, 0, result)); + sprintf (buf, "[cname=%s],%s", NISENTRYVAL(0, 0, result), + tablename_val); nis_freeresult (result); - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + result = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { @@ -254,31 +304,37 @@ enum nss_status _nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[100]; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - snprintf (buf, sizeof (buf), "[number=%d],rpc.org_dir", number); + { + int parse_res; + nis_result *result; + char buf[100 + tablename_len]; - result = nis_list(buf, EXPAND_NAME, NULL, NULL); + snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (result->status); + result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); - nis_freeresult (result); - return status; - } + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); - parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen); + nis_freeresult (result); + return status; + } - nis_freeresult (result); + parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen); - if (parse_res) - return NSS_STATUS_SUCCESS; + nis_freeresult (result); - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-service.c b/nis/nss_nisplus/nisplus-service.c index 6cad42d4f6..50bc7e24c1 100644 --- a/nis/nss_nisplus/nisplus-service.c +++ b/nis/nss_nisplus/nisplus-service.c @@ -31,107 +31,154 @@ __libc_lock_define_initialized (static, lock); static nis_result *result = NULL; -static nis_name *names = NULL; - -#define ENTNAME servent -#define DATABASE "services" -#define TRAILING_LIST_MEMBER s_aliases -#define TRAILING_LIST_SEPARATOR_P isspace -#include "../../nss/nss_files/files-parse.c" -#define ISSLASH(c) ((c) == '/') -LINE_PARSER -("#", - STRING_FIELD (result->s_name, isspace, 1); - INT_FIELD (result->s_port, ISSLASH, 10, 0, htons); - STRING_FIELD (result->s_proto, isspace, 1); - ) - +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; #define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) #define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) static int _nss_nisplus_parse_servent (nis_result *result, struct servent *serv, char *buffer, size_t buflen) { - char *p = buffer; + char *first_unused = buffer; size_t room_left = buflen; unsigned int i; - struct parser_data *data = (void *) buffer; + char *p, *line; if (result == NULL) return 0; if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "services_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val->EN_data.en_type, + "services_tbl") != 0 || + result->objects.objects_val->EN_data.en_cols.en_cols_len < 4) return 0; - memset (p, '\0', room_left); - - /* Generate the services entry format and use the normal parser */ - if (NISENTRYLEN (0, 0, result) + 1 > room_left) + if (NISENTRYLEN (0, 0, result) >= room_left) { + no_more_room: __set_errno (ERANGE); return 0; } - strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); - room_left -= (NISENTRYLEN (0, 0, result) + 1); - - if (NISENTRYLEN (0, 3, result) + 1 > room_left) + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN (0, 0, result)] = '\0'; + serv->s_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN (0, 2, result) >= room_left) + goto no_more_room; + strncpy (first_unused, NISENTRYVAL (0, 2, result), + NISENTRYLEN (0, 2, result)); + first_unused[NISENTRYLEN (0, 2, result)] = '\0'; + serv->s_proto = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + serv->s_port = atoi (NISENTRYVAL (0, 3, result)); + p = first_unused; + + line = p; + for (i = 0; i < result->objects.objects_len; i++) { - __set_errno (ERANGE); - return 0; + if (strcmp (NISENTRYVAL (i, 1, result), serv->s_name) != 0) + { + if (NISENTRYLEN (i, 1, result) + 2 > room_left) + goto no_more_room; + p = stpcpy(p, " "); + p = stpncpy (p, NISENTRYVAL (i, 1, result), + NISENTRYLEN (i, 1, result)); + *p = '\0'; + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } } - strcat (p, "\t"); - strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result)); - room_left -= (NISENTRYLEN (0, 3, result) + 1); - if (NISENTRYLEN (0, 2, result) + 1 > room_left) + ++p; + first_unused = p; + + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + serv->s_aliases = (char **) first_unused; + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= (sizeof (char *)); + serv->s_aliases[0] = NULL; + + i = 0; + while (*line != '\0') { - __set_errno (ERANGE); - return 0; - } - strcat (p, "/"); - strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); - room_left -= (NISENTRYLEN (0, 2, result) + 1); + /* Skip leading blanks. */ + while (isspace (*line)) + line++; - for (i = 1; i < result->objects.objects_len; i++) - { - if (NISENTRYLEN (i, 1, result) + 1 > room_left) - { - __set_errno (ERANGE); - return 0; + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + + room_left -= sizeof (char *); + serv->s_aliases[i] = line; + + while (*line != '\0' && *line != ' ') + ++line; + + if (*line == ' ') + { + *line = '\0'; + ++line; + ++i; } - strcat (p, " "); - strcat (p, NISENTRYVAL (i, 1, result)); - room_left -= (NISENTRYLEN (i, 1, result) + 1); + else + serv->s_aliases[i+1] = NULL; } - return _nss_files_parse_servent (p, serv, data, buflen); + return 1; +} + +static enum nss_status +_nss_create_tablename (void) +{ + if (tablename_val == NULL) + { + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "services.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); + } + return NSS_STATUS_SUCCESS; } + enum nss_status _nss_nisplus_setservent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + status = _nss_create_tablename (); __libc_lock_unlock (lock); - return NSS_STATUS_SUCCESS; + return status; } enum nss_status @@ -142,11 +189,6 @@ _nss_nisplus_endservent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -164,11 +206,11 @@ internal_nisplus_getservent_r (struct servent *serv, char *buffer, { if (result == NULL) { - names = nis_getnames ("services.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry (names[0]); + result = nis_first_entry (tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -176,7 +218,7 @@ internal_nisplus_getservent_r (struct servent *serv, char *buffer, { nis_result *res; - res = nis_next_entry (names[0], &result->cookie); + res = nis_next_entry (tablename_val, &result->cookie); nis_freeresult (result); result = res; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -212,6 +254,10 @@ _nss_nisplus_getservbyname_r (const char *name, const char *protocol, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL || protocol == NULL) { __set_errno (EINVAL); @@ -220,29 +266,30 @@ _nss_nisplus_getservbyname_r (const char *name, const char *protocol, else { nis_result *result; - char buf[strlen (name) + 255]; + char buf[strlen (name) + 255 + tablename_len]; /* Search at first in the alias list, and use the correct name for the next search */ - sprintf (buf, "[name=%s,proto=%s],services.org_dir", name, - protocol); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + sprintf (buf, "[name=%s,proto=%s],%s", name, protocol, + tablename_val); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); /* If we do not find it, try it as original name. But if the database is correct, we should find it in the first case, too */ if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + __type_of (result->objects.objects_val) != ENTRY_OBJ || + strcmp (result->objects.objects_val->EN_data.en_type, "services_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) - sprintf (buf, "[cname=%s,proto=%s],services.org_dir", name, protocol); + result->objects.objects_val->EN_data.en_cols.en_cols_len < 4) + sprintf (buf, "[cname=%s,proto=%s],%s", name, protocol, + tablename_val); else - sprintf (buf, "[cname=%s,proto=%s],services.org_dir", - NISENTRYVAL (0, 0, result), protocol); + sprintf (buf, "[cname=%s,proto=%s],%s", + NISENTRYVAL (0, 0, result), protocol, tablename_val); nis_freeresult (result); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { @@ -271,38 +318,44 @@ _nss_nisplus_getservbynumber_r (const int number, const char *protocol, struct servent *serv, char *buffer, size_t buflen) { - int parse_res; - nis_result *result; - char buf[60 + strlen (protocol)]; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; if (protocol == NULL) { __set_errno (EINVAL); return NSS_STATUS_NOTFOUND; } + else + { + int parse_res; + nis_result *result; + char buf[60 + strlen (protocol) + tablename_len]; - snprintf (buf, sizeof (buf), "[number=%d,proto=%s],services.org_dir", - number, protocol); + snprintf (buf, sizeof (buf), "[number=%d,proto=%s],%s", + number, protocol, tablename_val); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); - if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (result->status); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); - nis_freeresult (result); - return status; - } + nis_freeresult (result); + return status; + } - parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen); + parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen); - nis_freeresult (result); + nis_freeresult (result); - if (parse_res) - return NSS_STATUS_SUCCESS; + if (parse_res) + return NSS_STATUS_SUCCESS; - if (!parse_res && errno == ERANGE) - return NSS_STATUS_TRYAGAIN; - else - return NSS_STATUS_NOTFOUND; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } } diff --git a/nis/nss_nisplus/nisplus-spwd.c b/nis/nss_nisplus/nisplus-spwd.c index e6ff674f30..81bde4e689 100644 --- a/nis/nss_nisplus/nisplus-spwd.c +++ b/nis/nss_nisplus/nisplus-spwd.c @@ -26,132 +26,45 @@ #include <rpcsvc/nislib.h> #include "nss-nisplus.h" +#include "nisplus-parser.h" __libc_lock_define_initialized (static, lock) static nis_result *result = NULL; -static nis_name *names = NULL; +static nis_name tablename_val = NULL; +static u_long tablename_len = 0; -#define NISENTRYVAL(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) - -#define NISENTRYLEN(idx,col,res) \ - ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) - -int -_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp, - char *buffer, size_t buflen) +static enum nss_status +_nss_create_tablename (void) { - char *first_unused = buffer; - size_t room_left = buflen; - - if (result == NULL) - return 0; - - if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || - result->objects.objects_len != 1 || - result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || - strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, - "passwd_tbl") != 0 || - result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 8) - return 0; - - if (NISENTRYLEN(0, 0, result) >= room_left) - { - /* The line is too long for our buffer. */ - no_more_room: - __set_errno (ERANGE); - return 0; - } - - strncpy (first_unused, NISENTRYVAL (0, 0, result), - NISENTRYLEN (0, 0, result)); - first_unused[NISENTRYLEN(0, 0, result)] = '\0'; - sp->sp_namp = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - if (NISENTRYLEN(0, 1, result) >= room_left) - goto no_more_room; - - strncpy (first_unused, NISENTRYVAL (0, 1, result), - NISENTRYLEN (0, 1, result)); - first_unused[NISENTRYLEN(0, 1, result)] = '\0'; - sp->sp_pwdp = first_unused; - room_left -= (strlen (first_unused) +1); - first_unused += strlen (first_unused) +1; - - sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact = - sp->sp_expire = sp->sp_flag = -1; - - if (NISENTRYVAL (0, 7, result) != NULL) + if (tablename_val == NULL) { - char *line, *cp; - - line = NISENTRYVAL (0, 7, result); - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_lstchg = atol (line); - - line = cp; - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_min = atol(line); - - line = cp; - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_max = atol(line); - - line = cp; - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_warn = atol(line); - - line = cp; - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_inact = atol(line); - - line = cp; - cp = strchr (line, ':'); - if (cp == NULL) - return 0; - *cp++ = '\0'; - sp->sp_expire = atol(line); - - line = cp; - if (line == NULL) - return 0; - sp->sp_flag = atol(line); + char buf [40 + strlen (nis_local_directory ())]; + char *p; + + p = stpcpy (buf, "passwd.org_dir."); + p = stpcpy (p, nis_local_directory ()); + tablename_val = strdup (buf); + if (tablename_val == NULL) + return NSS_STATUS_TRYAGAIN; + tablename_len = strlen (tablename_val); } - - return 1; + return NSS_STATUS_SUCCESS; } enum nss_status _nss_nisplus_setspent (void) { + enum nss_status status = NSS_STATUS_SUCCESS; + __libc_lock_lock (lock); if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } + + if (tablename_val == NULL) + status = _nss_create_tablename (); __libc_lock_unlock (lock); @@ -166,11 +79,6 @@ _nss_nisplus_endspent (void) if (result) nis_freeresult (result); result = NULL; - if (names) - { - nis_freenames (names); - names = NULL; - } __libc_lock_unlock (lock); @@ -187,11 +95,11 @@ internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen) { if (result == NULL) { - names = nis_getnames ("passwd.org_dir"); - if (names == NULL || names[0] == NULL) - return NSS_STATUS_UNAVAIL; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; - result = nis_first_entry (names[0]); + result = nis_first_entry (tablename_val); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) return niserr2nss (result->status); } @@ -199,7 +107,7 @@ internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen) { nis_result *res; - res = nis_next_entry (names[0], &result->cookie); + res = nis_next_entry (tablename_val, &result->cookie); nis_freeresult (result); result = res; if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) @@ -232,16 +140,20 @@ _nss_nisplus_getspnam_r (const char *name, struct spwd *sp, { int parse_res; + if (tablename_val == NULL) + if (_nss_create_tablename () != NSS_STATUS_SUCCESS) + return NSS_STATUS_UNAVAIL; + if (name == NULL || strlen (name) > 8) return NSS_STATUS_NOTFOUND; else { nis_result *result; - char buf[strlen (name) + 24]; + char buf[strlen (name) + 24 + tablename_len]; - sprintf (buf, "[name=%s],passwd.org_dir", name); + sprintf (buf, "[name=%s],%s", name, tablename_val); - result = nis_list (buf, EXPAND_NAME, NULL, NULL); + result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) { |