|
Packit |
6bd9ab |
/*
|
|
Packit |
6bd9ab |
common.c - common server code routines
|
|
Packit |
6bd9ab |
This file is part of the nss-pam-ldapd library.
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
Copyright (C) 2006 West Consulting
|
|
Packit |
6bd9ab |
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Arthur de Jong
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
This library is free software; you can redistribute it and/or
|
|
Packit |
6bd9ab |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
License as published by the Free Software Foundation; either
|
|
Packit |
6bd9ab |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
This library is distributed in the hope that it will be useful,
|
|
Packit |
6bd9ab |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6bd9ab |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6bd9ab |
Lesser General Public License for more details.
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
License along with this library; if not, write to the Free Software
|
|
Packit |
6bd9ab |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
6bd9ab |
02110-1301 USA
|
|
Packit |
6bd9ab |
*/
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#include "config.h"
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#include <stdio.h>
|
|
Packit |
6bd9ab |
#include <stdarg.h>
|
|
Packit |
6bd9ab |
#include <sys/types.h>
|
|
Packit |
6bd9ab |
#include <sys/socket.h>
|
|
Packit |
6bd9ab |
#include <netinet/in.h>
|
|
Packit |
6bd9ab |
#include <arpa/inet.h>
|
|
Packit |
6bd9ab |
#include <strings.h>
|
|
Packit |
6bd9ab |
#include <limits.h>
|
|
Packit |
6bd9ab |
#include <netdb.h>
|
|
Packit |
6bd9ab |
#include <string.h>
|
|
Packit |
6bd9ab |
#include <regex.h>
|
|
Packit |
6bd9ab |
#include <stdlib.h>
|
|
Packit |
6bd9ab |
#include <signal.h>
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#include "nslcd.h"
|
|
Packit |
6bd9ab |
#include "common.h"
|
|
Packit |
6bd9ab |
#include "log.h"
|
|
Packit |
6bd9ab |
#include "attmap.h"
|
|
Packit |
6bd9ab |
#include "cfg.h"
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* simple wrapper around snptintf() to return non-zero in case
|
|
Packit |
6bd9ab |
of any failure (but always keep string 0-terminated) */
|
|
Packit |
6bd9ab |
int mysnprintf(char *buffer, size_t buflen, const char *format, ...)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
int res;
|
|
Packit |
6bd9ab |
va_list ap;
|
|
Packit |
6bd9ab |
/* do snprintf */
|
|
Packit |
6bd9ab |
va_start(ap, format);
|
|
Packit |
6bd9ab |
res = vsnprintf(buffer, buflen, format, ap);
|
|
Packit |
6bd9ab |
va_end(ap);
|
|
Packit |
6bd9ab |
/* NULL-terminate the string just to be on the safe side */
|
|
Packit |
6bd9ab |
buffer[buflen - 1] = '\0';
|
|
Packit |
6bd9ab |
/* check if the string was completely written */
|
|
Packit |
6bd9ab |
return ((res < 0) || (((size_t)res) >= buflen));
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* get a name of a signal with a given signal number */
|
|
Packit |
6bd9ab |
const char *signame(int signum)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
switch (signum)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
case SIGHUP: return "SIGHUP"; /* Hangup detected */
|
|
Packit |
6bd9ab |
case SIGINT: return "SIGINT"; /* Interrupt from keyboard */
|
|
Packit |
6bd9ab |
case SIGQUIT: return "SIGQUIT"; /* Quit from keyboard */
|
|
Packit |
6bd9ab |
case SIGILL: return "SIGILL"; /* Illegal Instruction */
|
|
Packit |
6bd9ab |
case SIGABRT: return "SIGABRT"; /* Abort signal from abort(3) */
|
|
Packit |
6bd9ab |
case SIGFPE: return "SIGFPE"; /* Floating point exception */
|
|
Packit |
6bd9ab |
case SIGKILL: return "SIGKILL"; /* Kill signal */
|
|
Packit |
6bd9ab |
case SIGSEGV: return "SIGSEGV"; /* Invalid memory reference */
|
|
Packit |
6bd9ab |
case SIGPIPE: return "SIGPIPE"; /* Broken pipe */
|
|
Packit |
6bd9ab |
case SIGALRM: return "SIGALRM"; /* Timer signal from alarm(2) */
|
|
Packit |
6bd9ab |
case SIGTERM: return "SIGTERM"; /* Termination signal */
|
|
Packit |
6bd9ab |
case SIGUSR1: return "SIGUSR1"; /* User-defined signal 1 */
|
|
Packit |
6bd9ab |
case SIGUSR2: return "SIGUSR2"; /* User-defined signal 2 */
|
|
Packit |
6bd9ab |
case SIGCHLD: return "SIGCHLD"; /* Child stopped or terminated */
|
|
Packit |
6bd9ab |
case SIGCONT: return "SIGCONT"; /* Continue if stopped */
|
|
Packit |
6bd9ab |
case SIGSTOP: return "SIGSTOP"; /* Stop process */
|
|
Packit |
6bd9ab |
case SIGTSTP: return "SIGTSTP"; /* Stop typed at tty */
|
|
Packit |
6bd9ab |
case SIGTTIN: return "SIGTTIN"; /* tty input for background process */
|
|
Packit |
6bd9ab |
case SIGTTOU: return "SIGTTOU"; /* tty output for background process */
|
|
Packit |
6bd9ab |
#ifdef SIGBUS
|
|
Packit |
6bd9ab |
case SIGBUS: return "SIGBUS"; /* Bus error */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGPOLL
|
|
Packit |
6bd9ab |
case SIGPOLL: return "SIGPOLL"; /* Pollable event */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGPROF
|
|
Packit |
6bd9ab |
case SIGPROF: return "SIGPROF"; /* Profiling timer expired */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGSYS
|
|
Packit |
6bd9ab |
case SIGSYS: return "SIGSYS"; /* Bad argument to routine */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGTRAP
|
|
Packit |
6bd9ab |
case SIGTRAP: return "SIGTRAP"; /* Trace/breakpoint trap */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGURG
|
|
Packit |
6bd9ab |
case SIGURG: return "SIGURG"; /* Urgent condition on socket */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGVTALRM
|
|
Packit |
6bd9ab |
case SIGVTALRM: return "SIGVTALRM"; /* Virtual alarm clock */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGXCPU
|
|
Packit |
6bd9ab |
case SIGXCPU: return "SIGXCPU"; /* CPU time limit exceeded */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
#ifdef SIGXFSZ
|
|
Packit |
6bd9ab |
case SIGXFSZ: return "SIGXFSZ"; /* File size limit exceeded */
|
|
Packit |
6bd9ab |
#endif
|
|
Packit |
6bd9ab |
default: return "UNKNOWN";
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* return the fully qualified domain name of the current host */
|
|
Packit |
6bd9ab |
const char *getfqdn(void)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
static char *fqdn = NULL;
|
|
Packit |
6bd9ab |
char hostname[BUFLEN_HOSTNAME];
|
|
Packit |
6bd9ab |
int hostnamelen;
|
|
Packit |
6bd9ab |
int i;
|
|
Packit |
6bd9ab |
struct hostent *host = NULL;
|
|
Packit |
6bd9ab |
/* if we already have a fqdn return that */
|
|
Packit |
6bd9ab |
if (fqdn != NULL)
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
/* get system hostname */
|
|
Packit |
6bd9ab |
if (gethostname(hostname, sizeof(hostname)) < 0)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_ERR, "gethostname() failed: %s", strerror(errno));
|
|
Packit |
6bd9ab |
return NULL;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
hostnamelen = strlen(hostname);
|
|
Packit |
6bd9ab |
/* lookup hostent */
|
|
Packit |
6bd9ab |
host = gethostbyname(hostname);
|
|
Packit |
6bd9ab |
if (host == NULL)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_ERR, "gethostbyname(%s): %s", hostname, hstrerror(h_errno));
|
|
Packit |
6bd9ab |
/* fall back to hostname */
|
|
Packit |
6bd9ab |
fqdn = strdup(hostname);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* check h_name for fqdn starting with our hostname */
|
|
Packit |
6bd9ab |
if ((strncasecmp(hostname, host->h_name, hostnamelen) == 0) &&
|
|
Packit |
6bd9ab |
(host->h_name[hostnamelen] == '.') &&
|
|
Packit |
6bd9ab |
(host->h_name[hostnamelen + 1] != '\0'))
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
fqdn = strdup(host->h_name);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* also check h_aliases */
|
|
Packit |
6bd9ab |
for (i = 0; host->h_aliases[i] != NULL; i++)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
if ((strncasecmp(hostname, host->h_aliases[i], hostnamelen) == 0) &&
|
|
Packit |
6bd9ab |
(host->h_aliases[i][hostnamelen] == '.') &&
|
|
Packit |
6bd9ab |
(host->h_aliases[i][hostnamelen + 1] != '\0'))
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
fqdn = strdup(host->h_aliases[i]);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* fall back to h_name if it has a dot in it */
|
|
Packit |
6bd9ab |
if (strchr(host->h_name, '.') != NULL)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
fqdn = strdup(host->h_name);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* also check h_aliases */
|
|
Packit |
6bd9ab |
for (i = 0; host->h_aliases[i] != NULL; i++)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
if (strchr(host->h_aliases[i], '.') != NULL)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
fqdn = strdup(host->h_aliases[i]);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* nothing found, fall back to hostname */
|
|
Packit |
6bd9ab |
fqdn = strdup(hostname);
|
|
Packit |
6bd9ab |
return fqdn;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
const char *get_userpassword(MYLDAP_ENTRY *entry, const char *attr,
|
|
Packit |
6bd9ab |
char *buffer, size_t buflen)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
const char *tmpvalue;
|
|
Packit |
6bd9ab |
/* get the value */
|
|
Packit |
6bd9ab |
tmpvalue = attmap_get_value(entry, attr, buffer, buflen);
|
|
Packit |
6bd9ab |
if (tmpvalue == NULL)
|
|
Packit |
6bd9ab |
return NULL;
|
|
Packit |
6bd9ab |
/* go over the entries and return the remainder of the value if it
|
|
Packit |
6bd9ab |
starts with {crypt} or crypt$ */
|
|
Packit |
6bd9ab |
if (strncasecmp(tmpvalue, "{crypt}", 7) == 0)
|
|
Packit |
6bd9ab |
return tmpvalue + 7;
|
|
Packit |
6bd9ab |
if (strncasecmp(tmpvalue, "crypt$", 6) == 0)
|
|
Packit |
6bd9ab |
return tmpvalue + 6;
|
|
Packit |
6bd9ab |
/* just return the first value completely */
|
|
Packit |
6bd9ab |
return tmpvalue;
|
|
Packit |
6bd9ab |
/* TODO: support more password formats e.g. SMD5
|
|
Packit |
6bd9ab |
(which is $1$ but in a different format)
|
|
Packit |
6bd9ab |
(any code for this is more than welcome) */
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* Checks if the specified name seems to be a valid user or group name. */
|
|
Packit |
6bd9ab |
int isvalidname(const char *name)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
return regexec(&nslcd_cfg->validnames, name, 0, NULL, 0) == 0;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* this writes a single address to the stream */
|
|
Packit |
6bd9ab |
int write_address(TFILE *fp, MYLDAP_ENTRY *entry, const char *attr,
|
|
Packit |
6bd9ab |
const char *addr)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
int32_t tmpint32;
|
|
Packit |
6bd9ab |
struct in_addr ipv4addr;
|
|
Packit |
6bd9ab |
struct in6_addr ipv6addr;
|
|
Packit |
6bd9ab |
/* try to parse the address as IPv4 first, fall back to IPv6 */
|
|
Packit |
6bd9ab |
if (inet_pton(AF_INET, addr, &ipv4addr) > 0)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
/* write address type */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, AF_INET);
|
|
Packit |
6bd9ab |
/* write the address length */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, sizeof(struct in_addr));
|
|
Packit |
6bd9ab |
/* write the address itself (in network byte order) */
|
|
Packit |
6bd9ab |
WRITE(fp, &ipv4addr, sizeof(struct in_addr));
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
else if (inet_pton(AF_INET6, addr, &ipv6addr) > 0)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
/* write address type */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, AF_INET6);
|
|
Packit |
6bd9ab |
/* write the address length */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, sizeof(struct in6_addr));
|
|
Packit |
6bd9ab |
/* write the address itself (in network byte order) */
|
|
Packit |
6bd9ab |
WRITE(fp, &ipv6addr, sizeof(struct in6_addr));
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
else
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
/* failure, log but write simple invalid address
|
|
Packit |
6bd9ab |
(otherwise the address list is messed up) */
|
|
Packit |
6bd9ab |
/* TODO: have error message in correct format */
|
|
Packit |
6bd9ab |
log_log(LOG_WARNING, "%s: %s: \"%s\" unparsable",
|
|
Packit |
6bd9ab |
myldap_get_dn(entry), attr, addr);
|
|
Packit |
6bd9ab |
/* write an illegal address type */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, -1);
|
|
Packit |
6bd9ab |
/* write an emtpy address */
|
|
Packit |
6bd9ab |
WRITE_INT32(fp, 0);
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* we're done */
|
|
Packit |
6bd9ab |
return 0;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
int read_address(TFILE *fp, char *addr, int *addrlen, int *af)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
int32_t tmpint32;
|
|
Packit |
6bd9ab |
int len;
|
|
Packit |
6bd9ab |
/* read address family */
|
|
Packit |
6bd9ab |
READ_INT32(fp, *af);
|
|
Packit |
6bd9ab |
if ((*af != AF_INET) && (*af != AF_INET6))
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_WARNING, "incorrect address family specified: %d", *af);
|
|
Packit |
6bd9ab |
return -1;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* read address length */
|
|
Packit |
6bd9ab |
READ_INT32(fp, len);
|
|
Packit |
6bd9ab |
if ((len > *addrlen) || (len <= 0))
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_WARNING, "address length incorrect: %d", len);
|
|
Packit |
6bd9ab |
return -1;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
*addrlen = len;
|
|
Packit |
6bd9ab |
/* read address */
|
|
Packit |
6bd9ab |
READ(fp, addr, len);
|
|
Packit |
6bd9ab |
/* we're done */
|
|
Packit |
6bd9ab |
return 0;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* convert the provided string representation of a sid
|
|
Packit |
6bd9ab |
(e.g. S-1-5-21-1936905831-823966427-12391542-23578)
|
|
Packit |
6bd9ab |
to a format that can be used to search the objectSid property with */
|
|
Packit |
6bd9ab |
char *sid2search(const char *sid)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
const char *tmpsid = sid;
|
|
Packit |
6bd9ab |
char *res, *tmp;
|
|
Packit |
6bd9ab |
int i = 0;
|
|
Packit |
6bd9ab |
unsigned long int l;
|
|
Packit |
6bd9ab |
/* check the beginning of the string */
|
|
Packit |
6bd9ab |
if (strncasecmp(sid, "S-", 2) != 0)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_ERR, "error in SID %s", sid);
|
|
Packit |
6bd9ab |
exit(EXIT_FAILURE);
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* count the number of dashes in the sid */
|
|
Packit |
6bd9ab |
while (tmpsid != NULL)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
i++;
|
|
Packit |
6bd9ab |
tmpsid = strchr(tmpsid + 1, '-');
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
i -= 2; /* number of security ids plus one because we add the uid later */
|
|
Packit |
6bd9ab |
/* allocate memory */
|
|
Packit |
6bd9ab |
res = malloc(3 + 3 + 6 * 3 + i * 4 * 3 + 1);
|
|
Packit |
6bd9ab |
if (res == NULL)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
log_log(LOG_CRIT, "malloc() failed to allocate memory");
|
|
Packit |
6bd9ab |
exit(1);
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
/* build the first part */
|
|
Packit |
6bd9ab |
l = strtoul(sid + 2, &tmp, 10);
|
|
Packit |
6bd9ab |
sprintf(res, "\\%02x\\%02x", (unsigned int)l & 0xff, (unsigned int)i);
|
|
Packit |
6bd9ab |
/* build authority part (we only handle 32 of the 48 bits) */
|
|
Packit |
6bd9ab |
l = strtoul(tmp + 1, &tmp, 10);
|
|
Packit |
6bd9ab |
sprintf(res + strlen(res), "\\00\\00\\%02x\\%02x\\%02x\\%02x",
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 24) & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 16) & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 8) & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)(l & 0xff));
|
|
Packit |
6bd9ab |
/* go over the rest of the bits */
|
|
Packit |
6bd9ab |
while (*tmp != '\0')
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
l = strtoul(tmp + 1, &tmp, 10);
|
|
Packit |
6bd9ab |
sprintf(res + strlen(res), "\\%02x\\%02x\\%02x\\%02x",
|
|
Packit |
6bd9ab |
(unsigned int)(l & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 8) & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 16) & 0xff),
|
|
Packit |
6bd9ab |
(unsigned int)((l >> 24) & 0xff));
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
return res;
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* return the last security identifier of the binary sid */
|
|
Packit |
6bd9ab |
unsigned long int binsid2id(const char *binsid)
|
|
Packit |
6bd9ab |
{
|
|
Packit |
6bd9ab |
int i;
|
|
Packit |
6bd9ab |
/* find the position of the last security id */
|
|
Packit |
6bd9ab |
i = 2 + 6 + ((((unsigned int)binsid[1]) & 0xff) - 1) * 4;
|
|
Packit |
6bd9ab |
return (((unsigned long int)binsid[i]) & 0xff) |
|
|
Packit |
6bd9ab |
((((unsigned long int)binsid[i + 1]) & 0xff) << 8) |
|
|
Packit |
6bd9ab |
((((unsigned long int)binsid[i + 2]) & 0xff) << 16) |
|
|
Packit |
6bd9ab |
((((unsigned long int)binsid[i + 3]) & 0xff) << 24);
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit Service |
574307 |
/* provide a strtoid() implementation, similar to strtoul() but returning
|
|
Packit Service |
574307 |
an range-checked uint32_t instead */
|
|
Packit Service |
574307 |
unsigned int strtoid(const char *nptr,char **endptr,int base)
|
|
Packit |
6bd9ab |
{
|
|
Packit Service |
574307 |
long long val;
|
|
Packit Service |
574307 |
/* use the fact that long long is 64-bit, even on 32-bit systems */
|
|
Packit Service |
574307 |
val=strtoll(nptr,endptr,base);
|
|
Packit Service |
574307 |
if (val>UINT32_MAX)
|
|
Packit |
6bd9ab |
{
|
|
Packit Service |
574307 |
errno=ERANGE;
|
|
Packit Service |
574307 |
return UINT32_MAX;
|
|
Packit |
6bd9ab |
}
|
|
Packit Service |
574307 |
else if (val < 0)
|
|
Packit Service |
574307 |
{
|
|
Packit Service |
574307 |
errno=EINVAL;
|
|
Packit Service |
574307 |
return UINT32_MAX;
|
|
Packit Service |
574307 |
}
|
|
Packit Service |
574307 |
/* If errno was set, we'll pass it back as-is */
|
|
Packit Service |
574307 |
return (uint32_t)val;
|
|
Packit |
6bd9ab |
}
|