radsecproxy-1.11.1/0000755000076600000240000000000014724611072007702 5radsecproxy-1.11.1/tcp.h0000644000076600000240000000030313320713715010553 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ const struct protodefs *tcpinit(uint8_t h); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/acinclude.m40000644000076600000240000000010314722543325012010 m4_include(ax_check_openssl.m4) m4_include(ax_build_date_epoch.m4) radsecproxy-1.11.1/radsecproxy.c0000644000076600000240000040017414722547207012345 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2010-2013,2015-2016, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ /* For UDP there is one server instance consisting of udpserverrd and udpserverth * rd is responsible for init and launching wr * For TLS there is a server instance that launches tlsserverrd for each TLS peer * each tlsserverrd launches tlsserverwr * For each UDP/TLS peer there is clientrd and clientwr, clientwr is responsible * for init and launching rd * * serverrd will receive a request, processes it and puts it in the requestq of * the appropriate clientwr * clientwr monitors its requestq and sends requests * clientrd looks for responses, processes them and puts them in the replyq of * the peer the request came from * serverwr monitors its reply and sends replies * * In addition to the main thread, we have: * If UDP peers are configured, there will be 2 + 2 * #peers UDP threads * If TLS peers are configured, there will initially be 2 * #peers TLS threads * For each TLS peer connecting to us there will be 2 more TLS threads * This is only for connected peers * Example: With 3 UDP peers and 30 TLS peers, there will be a max of * 1 + (2 + 2 * 3) + (2 * 30) + (2 * 30) = 129 threads */ /* Bugs: * May segfault when dtls connections go down? More testing needed * Remove expired stuff from clients request list? * Multiple outgoing connections if not enough IDs? (multiple servers per conf?) * Useful for TCP accounting? Now we require separate server config for alt port */ #define _GNU_SOURCE #include #include #include #include #include #include #include #if defined(HAVE_MALLOPT) #include #endif #ifdef SYS_SOLARIS #include #endif #include "debug.h" #include "dns.h" #include "dtls.h" #include "fticks.h" #include "fticks_hashmac.h" #include "hash.h" #include "hostport.h" #include "radsecproxy.h" #include "tcp.h" #include "tls.h" #include "udp.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct options options; static struct list *clconfs, *srvconfs; static struct list *realms; #ifdef __CYGWIN__ extern int __declspec(dllimport) optind; extern char __declspec(dllimport) * optarg; #else extern int optind; extern char *optarg; #endif static const struct protodefs *protodefs[RAD_PROTOCOUNT]; pthread_attr_t pthread_attr; /* minimum required declarations to avoid reordering code */ struct realm *adddynamicrealmserver(struct realm *realm, char *id); void *clientwr(void *arg); int compileserverconfig(struct clsrvconf *conf, const char *block); int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src); int dynamicconfig(struct server *server); int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val); void freerealm(struct realm *realm); void freeclsrvconf(struct clsrvconf *conf); void freerq(struct request *rq); void freerqoutdata(struct rqout *rqout); void rmclientrq(struct request *rq, uint8_t id); static const struct protodefs *(*protoinits[])(uint8_t) = {udpinit, tlsinit, tcpinit, dtlsinit}; uint8_t protoname2int(const char *name) { uint8_t i; for (i = 0; i < RAD_PROTOCOUNT; i++) if (protodefs[i] && protodefs[i]->name && !strcasecmp(protodefs[i]->name, name)) return i; return 255; } /* returns 1 if the len first bits are equal, else 0 */ int prefixmatch(void *a1, void *a2, uint8_t len) { static uint8_t mask[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; uint8_t r, l = len / 8; if (l && memcmp(a1, a2, l)) return 0; r = len % 8; if (!r) return 1; return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]); } /* returns next config with matching address, or NULL */ struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur, uint8_t server_p, struct hostportres **hp) { struct list_node *entry; struct clsrvconf *conf; for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; if (conf->type == type && addressmatches(conf->hostports, addr, server_p, hp)) { if (cur) *cur = entry; return conf; } } return NULL; } struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur, struct hostportres **hp) { return find_conf(type, addr, clconfs, cur, 0, hp); } struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur) { return find_conf(type, addr, srvconfs, cur, 1, NULL); } struct list *find_all_clconf(uint8_t type, struct sockaddr *addr, struct list_node *cur, struct hostportres **hp) { struct list *list = list_create(); struct clsrvconf *ref = (struct clsrvconf *)cur->data; struct clsrvconf *next = ref; do { if (next->tlsconf == ref->tlsconf && next->pskid && next->pskkeylen) if (!list_push(list, next)) debug(DBG_ERR, "malloc failed"); } while ((next = find_clconf(type, addr, &cur, hp)) != NULL); return list; } /* returns next config of given type, or NULL */ struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur) { struct list_node *entry; struct clsrvconf *conf; for (entry = (cur && *cur ? list_next(*cur) : list_first(clconfs)); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; if (conf->type == type) { if (cur) *cur = entry; return conf; } } return NULL; } struct gqueue *newqueue(void) { struct gqueue *q; q = malloc(sizeof(struct gqueue)); if (!q) debugx(1, DBG_ERR, "malloc failed"); q->entries = list_create(); if (!q->entries) debugx(1, DBG_ERR, "malloc failed"); pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cond, NULL); return q; } void removequeue(struct gqueue *q) { struct list_node *entry; if (!q) return; pthread_mutex_lock(&q->mutex); for (entry = list_first(q->entries); entry; entry = list_next(entry)) freerq((struct request *)entry->data); list_free(q->entries); pthread_cond_destroy(&q->cond); pthread_mutex_unlock(&q->mutex); pthread_mutex_destroy(&q->mutex); free(q); } struct client *addclient(struct clsrvconf *conf, uint8_t lock) { struct client *new = NULL; if (lock) pthread_mutex_lock(conf->lock); if (!conf->clients) { conf->clients = list_create(); if (!conf->clients) { if (lock) pthread_mutex_unlock(conf->lock); debug(DBG_ERR, "malloc failed"); return NULL; } } new = calloc(1, sizeof(struct client)); if (!new) { debug(DBG_ERR, "malloc failed"); if (lock) pthread_mutex_unlock(conf->lock); return NULL; } if (!list_push(conf->clients, new)) { free(new); if (lock) pthread_mutex_unlock(conf->lock); return NULL; } new->conf = conf; if (conf->pdef->addclient) conf->pdef->addclient(new); else new->replyq = newqueue(); pthread_mutex_init(&new->lock, NULL); if (lock) pthread_mutex_unlock(conf->lock); return new; } pthread_mutex_t *removeclientrqs_sendrq_freeserver_lock(void) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; return &lock; } void removeclientrq(struct client *client, int i) { struct request *rq; struct rqout *rqout; rq = client->rqs[i]; if (!rq) return; pthread_mutex_lock(removeclientrqs_sendrq_freeserver_lock()); if (rq->to) { rqout = rq->to->requests + rq->newid; pthread_mutex_lock(rqout->lock); if (rqout->rq == rq) /* still pointing to our request */ freerqoutdata(rqout); pthread_mutex_unlock(rqout->lock); } client->rqs[i] = NULL; freerq(rq); pthread_mutex_unlock(removeclientrqs_sendrq_freeserver_lock()); } void removeclientrqs(struct client *client) { int i; for (i = 0; i < MAX_REQUESTS; i++) removeclientrq(client, i); } void removelockedclient(struct client *client) { struct clsrvconf *conf; conf = client->conf; if (conf->clients) { removeclientrqs(client); removequeue(client->replyq); list_removedata(conf->clients, client); pthread_mutex_destroy(&client->lock); free(client->addr); free(client); } } void removeclient(struct client *client) { struct clsrvconf *conf; if (!client) return; conf = client->conf; pthread_mutex_lock(conf->lock); removelockedclient(client); pthread_mutex_unlock(conf->lock); } void freeserver(struct server *server, uint8_t destroymutex) { struct rqout *rqout, *end; if (!server) return; pthread_mutex_lock(removeclientrqs_sendrq_freeserver_lock()); if (server->requests) { rqout = server->requests; for (end = rqout + MAX_REQUESTS; rqout < end; rqout++) { freerqoutdata(rqout); pthread_mutex_destroy(rqout->lock); free(rqout->lock); } free(server->requests); } free(server->dynamiclookuparg); if (server->ssl) { SSL_free(server->ssl); } if (destroymutex) { pthread_mutex_destroy(&server->lock); pthread_cond_destroy(&server->newrq_cond); pthread_mutex_destroy(&server->newrq_mutex); } pthread_mutex_unlock(removeclientrqs_sendrq_freeserver_lock()); free(server); } int addserver(struct clsrvconf *conf, const char *dynamiclookuparg) { int i; pthread_t clientth; if (conf->servers) { debug(DBG_ERR, "addserver: currently works with just one server per conf"); return 0; } conf->servers = malloc(sizeof(struct server)); if (!conf->servers) { debug(DBG_ERR, "malloc failed"); return 0; } memset(conf->servers, 0, sizeof(struct server)); conf->servers->conf = conf; conf->pdef->setsrcres(); conf->servers->sock = -1; if (conf->pdef->addserverextra) conf->pdef->addserverextra(conf); conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct rqout)); if (!conf->servers->requests) { debug(DBG_ERR, "malloc failed"); goto errexit; } for (i = 0; i < MAX_REQUESTS; i++) { conf->servers->requests[i].lock = malloc(sizeof(pthread_mutex_t)); if (!conf->servers->requests[i].lock) { debug(DBG_ERR, "malloc failed"); goto errexit; } if (pthread_mutex_init(conf->servers->requests[i].lock, NULL)) { debugerrno(errno, DBG_ERR, "mutex init failed"); free(conf->servers->requests[i].lock); conf->servers->requests[i].lock = NULL; goto errexit; } } if (pthread_mutex_init(&conf->servers->lock, NULL)) { debugerrno(errno, DBG_ERR, "mutex init failed"); goto errexit; } conf->servers->newrq = 0; conf->servers->conreset = 0; if (pthread_mutex_init(&conf->servers->newrq_mutex, NULL)) { debugerrno(errno, DBG_ERR, "mutex init failed"); pthread_mutex_destroy(&conf->servers->lock); goto errexit; } if (pthread_cond_init(&conf->servers->newrq_cond, NULL)) { debugerrno(errno, DBG_ERR, "mutex init failed"); pthread_mutex_destroy(&conf->servers->newrq_mutex); pthread_mutex_destroy(&conf->servers->lock); goto errexit; } conf->servers->state = conf->blockingstartup ? RSP_SERVER_STATE_BLOCKING_STARTUP : RSP_SERVER_STATE_STARTUP; if (conf->dynamiclookupcommand) conf->servers->dynamiclookuparg = stringcopy(dynamiclookuparg, 0); debug(DBG_DBG, "%s: starting new client writer for %s", __func__, conf->name); if (pthread_create(&clientth, &pthread_attr, clientwr, (void *)(conf->servers))) { debugerrno(errno, DBG_ERR, "addserver: pthread_create failed"); freeserver(conf->servers, 1); conf->servers = NULL; return 0; } else pthread_detach(clientth); return 1; errexit: freeserver(conf->servers, 0); conf->servers = NULL; return 0; } unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) { while (length > 1) { if (ATTRTYPE(attrs) == type) return attrs; length -= ATTRLEN(attrs); attrs += ATTRLEN(attrs); } return NULL; } struct request *newrqref(struct request *rq) { if (rq) { pthread_mutex_lock(&rq->refmutex); rq->refcount++; pthread_mutex_unlock(&rq->refmutex); } return rq; } void freerq(struct request *rq) { if (!rq) return; pthread_mutex_lock(&rq->refmutex); debug(DBG_DBG, "freerq: called with refcount %d", rq->refcount); if (--rq->refcount) { pthread_mutex_unlock(&rq->refmutex); return; } pthread_mutex_unlock(&rq->refmutex); if (rq->origusername) free(rq->origusername); if (rq->buf) { memset(rq->buf, 0, rq->buflen); free(rq->buf); } if (rq->replybuf && rq->replybuflen > 0) { memset(rq->replybuf, 0, rq->replybuflen); free(rq->replybuf); } if (rq->msg) radmsg_free(rq->msg); pthread_mutex_destroy(&rq->refmutex); free(rq); } void freerqoutdata(struct rqout *rqout) { if (!rqout) return; if (rqout->rq) { if (rqout->rq->buf) { free(rqout->rq->buf); rqout->rq->buf = NULL; } rqout->rq->to = NULL; freerq(rqout->rq); rqout->rq = NULL; } rqout->tries = 0; memset(&rqout->expiry, 0, sizeof(struct timeval)); } int _internal_sendrq(struct server *to, uint8_t id, struct request *rq) { if (!to->requests[id].rq) { pthread_mutex_lock(to->requests[id].lock); if (!to->requests[id].rq) { rq->newid = id; rq->msg->id = id; rq->buflen = radmsg2buf(rq->msg, to->conf->secret, to->conf->secret_len, &rq->buf); if (!rq->buf || rq->buflen <= 0) { pthread_mutex_unlock(to->requests[id].lock); debug(DBG_ERR, "sendrq: radmsg2buf failed"); return 0; } debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", id, to->conf->name); to->requests[id].rq = rq; pthread_mutex_unlock(to->requests[id].lock); return 1; } pthread_mutex_unlock(to->requests[id].lock); } return 0; } void sendrq(struct request *rq) { int i, start; struct server *to; pthread_mutex_lock(removeclientrqs_sendrq_freeserver_lock()); to = rq->to; if (!to) goto errexit; start = to->conf->statusserver == RSP_STATSRV_OFF ? 0 : 1; pthread_mutex_lock(&to->newrq_mutex); if (start && rq->msg->code == RAD_Status_Server) { if (!_internal_sendrq(to, 0, rq)) { debug(DBG_INFO, "sendrq: status server already in queue, dropping request"); goto errexit; } } else { if (!to->nextid) to->nextid = start; /* might simplify if only try nextid, might be ok */ for (i = to->nextid; i < MAX_REQUESTS; i++) { if (_internal_sendrq(to, i, rq)) break; } if (i == MAX_REQUESTS) { for (i = start; i < to->nextid; i++) { if (_internal_sendrq(to, i, rq)) break; } if (i == to->nextid) { debug(DBG_WARN, "sendrq: no room in queue for server %s, dropping request", to->conf->name); goto errexit; } } if (i >= start) /* i is not reserved for statusserver */ to->nextid = i + 1; } if (!to->newrq) { to->newrq = 1; debug(DBG_DBG, "sendrq: signalling client writer"); pthread_cond_signal(&to->newrq_cond); } pthread_mutex_unlock(&to->newrq_mutex); pthread_mutex_unlock(removeclientrqs_sendrq_freeserver_lock()); return; errexit: if (rq->from) rmclientrq(rq, rq->rqid); freerq(rq); if (to) pthread_mutex_unlock(&to->newrq_mutex); pthread_mutex_unlock(removeclientrqs_sendrq_freeserver_lock()); } void sendreply(struct request *rq) { uint8_t first; struct client *to = rq->from; if (!rq->replybuf) rq->replybuflen = radmsg2buf(rq->msg, to->conf->secret, to->conf->secret_len, &rq->replybuf); radmsg_free(rq->msg); rq->msg = NULL; if (!rq->replybuf || rq->replybuflen <= 0) { freerq(rq); debug(DBG_ERR, "sendreply: radmsg2buf failed"); return; } pthread_mutex_lock(&to->replyq->mutex); first = list_first(to->replyq->entries) == NULL; if (!list_push(to->replyq->entries, rq)) { pthread_mutex_unlock(&to->replyq->mutex); freerq(rq); debug(DBG_ERR, "sendreply: malloc failed"); return; } if (first) { debug(DBG_DBG, "signalling server writer"); pthread_cond_signal(&to->replyq->cond); } pthread_mutex_unlock(&to->replyq->mutex); } static int pwdcrypt(char encrypt_flag, uint8_t *in, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt, uint8_t saltlen) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct md5_ctx mdctx; unsigned char hash[MD5_DIGEST_SIZE], *input; uint8_t i, offset = 0, out[128]; pthread_mutex_lock(&lock); md5_init(&mdctx); input = auth; for (;;) { md5_update(&mdctx, sharedlen, shared); md5_update(&mdctx, 16, input); if (salt) { md5_update(&mdctx, saltlen, salt); salt = NULL; } md5_digest(&mdctx, sizeof(hash), hash); for (i = 0; i < 16; i++) out[offset + i] = hash[i] ^ in[offset + i]; if (encrypt_flag) input = out + offset; else input = in + offset; offset += 16; if (offset == len) break; } memcpy(in, out, len); pthread_mutex_unlock(&lock); return 1; } static int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct md5_ctx mdctx; unsigned char hash[MD5_DIGEST_SIZE]; uint8_t i, offset; pthread_mutex_lock(&lock); md5_init(&mdctx); #if 0 printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16); printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2); printfchars(NULL, "msppencrypt in", "%02x ", text, len); #endif md5_update(&mdctx, sharedlen, shared); md5_update(&mdctx, 16, auth); md5_update(&mdctx, 2, salt); md5_digest(&mdctx, sizeof(hash), hash); #if 0 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16); #endif for (i = 0; i < 16; i++) text[i] ^= hash[i]; for (offset = 16; offset < len; offset += 16) { #if 0 printf("text + offset - 16 c(%d): ", offset / 16); printfchars(NULL, NULL, "%02x ", text + offset - 16, 16); #endif md5_update(&mdctx, sharedlen, shared); md5_update(&mdctx, 16, text + offset - 16); md5_digest(&mdctx, sizeof(hash), hash); #if 0 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16); #endif for (i = 0; i < 16; i++) text[offset + i] ^= hash[i]; } #if 0 printfchars(NULL, "msppencrypt out", "%02x ", text, len); #endif pthread_mutex_unlock(&lock); return 1; } static int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct md5_ctx mdctx; unsigned char hash[MD5_DIGEST_SIZE]; uint8_t i, offset; char plain[255]; pthread_mutex_lock(&lock); md5_init(&mdctx); #if 0 printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16); printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2); printfchars(NULL, "msppdecrypt in", "%02x ", text, len); #endif md5_update(&mdctx, sharedlen, shared); md5_update(&mdctx, 16, auth); md5_update(&mdctx, 2, salt); md5_digest(&mdctx, sizeof(hash), hash); #if 0 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16); #endif for (i = 0; i < 16; i++) plain[i] = text[i] ^ hash[i]; for (offset = 16; offset < len; offset += 16) { #if 0 printf("text + offset - 16 c(%d): ", offset / 16); printfchars(NULL, NULL, "%02x ", text + offset - 16, 16); #endif md5_update(&mdctx, sharedlen, shared); md5_update(&mdctx, 16, text + offset - 16); md5_digest(&mdctx, sizeof(hash), hash); #if 0 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16); #endif for (i = 0; i < 16; i++) plain[offset + i] = text[offset + i] ^ hash[i]; } memcpy(text, plain, len); #if 0 printfchars(NULL, "msppdecrypt out", "%02x ", text, len); #endif pthread_mutex_unlock(&lock); return 1; } struct realm *newrealmref(struct realm *r) { if (r) { pthread_mutex_lock(&r->refmutex); r->refcount++; pthread_mutex_unlock(&r->refmutex); } return r; } /* returns with lock on realm */ struct realm *id2realm(struct list *realmlist, char *id) { struct list_node *entry; struct realm *realm, *subrealm; /* need to do locking for subrealms and check subrealm timers */ for (entry = list_first(realmlist); entry; entry = list_next(entry)) { realm = (struct realm *)entry->data; if (!regexec(&realm->regex, id, 0, NULL, 0)) { pthread_mutex_lock(&realm->mutex); if (realm->subrealms) { subrealm = id2realm(realm->subrealms, id); if (subrealm) { pthread_mutex_unlock(&realm->mutex); return subrealm; } } return newrealmref(realm); } } return NULL; } int hasdynamicserver(struct list *srvconfs) { struct list_node *entry; struct server *server; for (entry = list_first(srvconfs); entry; entry = list_next(entry)) if (((struct clsrvconf *)entry->data)->servers) { server = ((struct clsrvconf *)entry->data)->servers; pthread_mutex_lock(&server->lock); if (server->dynamiclookuparg && server->state != RSP_SERVER_STATE_FAILING) { pthread_mutex_unlock(&server->lock); return 1; } pthread_mutex_unlock(&server->lock); } return 0; } /** * @brief create a shallow clone of srv (i.e. copy srv, but keep all pointers) * if srv->parent is set (srv already is a clone), clone the parent instead. * * @param srv * @return struct clsrvconf* */ static struct clsrvconf *shallowcloneserver(struct clsrvconf *srv) { struct clsrvconf *clone; clone = malloc(sizeof(struct clsrvconf)); if (!clone) { debug(DBG_ERR, "malloc failed"); return NULL; } if (srv->parent) { *clone = *srv->parent; clone->parent = srv->parent; } else { *clone = *srv; clone->parent = srv; } clone->shallow = 1; return clone; } /** * @brief internal helper: search for srv in servers and replace value with shallow copy if found. * * @param servers * @param srv * @return 1 if srv was found in servers */ static int resetserversubrealm(struct list *servers, struct clsrvconf *srv) { struct list_node *entry; for (entry = list_first(servers); entry; entry = list_next(entry)) { if (entry->data == srv) { entry->data = shallowcloneserver(srv); return 1; } } return 0; } /** * @brief internal helper: clear srvconf list, freeing all associated memory * * @param srvconfs */ static void clearsrvconflist(struct realm *realm, struct list *srvconfs) { struct clsrvconf *srvconf; while ((srvconf = list_shift(srvconfs))) { if (srvconf->dynamiclookupcommand && !srvconf->servers) freeclsrvconf(srvconf); freerealm(realm); } list_destroy(srvconfs); } /* helper function, only used by removeserversubrealms() */ void _internal_removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) { struct list_node *entry; struct realm *realm; for (entry = list_first(realmlist); entry;) { realm = newrealmref((struct realm *)entry->data); /* might remove entry from the list, so determine next entry now */ entry = list_next(entry); pthread_mutex_lock(&realm->mutex); if (resetserversubrealm(realm->srvconfs, srv) | resetserversubrealm(realm->accsrvconfs, srv)) { /* remove subrealm if no dynamic servers left */ if (!hasdynamicserver(realm->srvconfs) && !hasdynamicserver(realm->accsrvconfs)) { clearsrvconflist(realm, realm->srvconfs); realm->srvconfs = NULL; clearsrvconflist(realm, realm->accsrvconfs); realm->accsrvconfs = NULL; list_removedata(realmlist, realm); debug(DBG_DBG, "removeserversubrealms: removing expired subrealm %s", realm->name); } } pthread_mutex_unlock(&realm->mutex); freerealm(realm); } } /** * @brief remove an active server from a subrealm * After completion, the caller has the only reference to srv and is responsible for freeing it. * The subrealm the server belonged to might be freed if there are no dynamic servers left, and * with it all srvconfs. * * @param realmlist the realmlist from which to remove the server * @param srv the server to remove */ void removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) { struct list_node *entry; struct realm *realm; for (entry = list_first(realmlist); entry; entry = list_next(entry)) { realm = (struct realm *)entry->data; pthread_mutex_lock(&realm->mutex); if (realm->subrealms) { _internal_removeserversubrealms(realm->subrealms, srv); if (!list_first(realm->subrealms)) { list_destroy(realm->subrealms); realm->subrealms = NULL; } } pthread_mutex_unlock(&realm->mutex); } } int pwdrecrypt(uint8_t *pwd, uint8_t len, uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len, uint8_t *oldauth, uint8_t *newauth, uint8_t *oldsalt, uint8_t oldsaltlen, uint8_t *newsalt, uint8_t newsaltlen) { if (len < 16 || len > 128 || len % 16) { debug(DBG_WARN, "pwdrecrypt: invalid password length"); return 0; } if (!pwdcrypt(0, pwd, len, oldsecret, oldsecret_len, oldauth, oldsalt, oldsaltlen)) { debug(DBG_WARN, "pwdrecrypt: cannot decrypt password"); return 0; } #ifdef DEBUG printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len); #endif if (!pwdcrypt(1, pwd, len, newsecret, newsecret_len, newauth, newsalt, newsaltlen)) { debug(DBG_WARN, "pwdrecrypt: cannot encrypt password"); return 0; } return 1; } int msmpprecrypt(uint8_t *msmpp, uint8_t len, uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len, uint8_t *oldauth, uint8_t *newauth) { if (len < 18) return 0; if (!msmppdecrypt(msmpp + 2, len - 2, oldsecret, oldsecret_len, oldauth, msmpp)) { debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key"); return 0; } if (!msmppencrypt(msmpp + 2, len - 2, newsecret, newsecret_len, newauth, msmpp)) { debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key"); return 0; } return 1; } int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq, uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len) { unsigned char *attr; for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) { debug(DBG_DBG, "msmppe: Got %s", attrtxt); if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, oldsecret_len, newsecret, newsecret_len, rq->buf + 4, rq->rqauth)) return 0; } return 1; } int rewriteusername(struct request *rq, struct tlv *attr) { char *orig = (char *)tlv2str(attr); if (!orig) return 0; if (!dorewritemodattr(attr, rq->from->conf->rewriteusername)) { free(orig); return 0; } if (strlen(orig) != attr->l || memcmp(orig, attr->v, attr->l)) rq->origusername = (char *)orig; else free(orig); return 1; } void addttlattr(struct radmsg *msg, uint32_t *attrtype, uint8_t addttl) { uint8_t ttl[4]; struct tlv *attr; memset(ttl, 0, 4); ttl[3] = addttl; if (attrtype[1] == 256) { /* not vendor */ attr = maketlv(attrtype[0], 4, ttl); if (attr && !radmsg_add(msg, attr, 0)) freetlv(attr); } else { attr = maketlv(attrtype[1], 4, ttl); if (attr) addvendorattr(msg, attrtype[0], attr); } } int decttl(uint8_t l, uint8_t *v) { int i; if (l == 0) return 0; i = l - 1; if (v[i]) { if (--v[i--]) return 1; while (i >= 0 && !v[i]) i--; return i >= 0; } for (i--; i >= 0 && !v[i];) i--; if (i < 0) return 0; v[i]--; while (++i < l) v[i] = 255; return 1; } /* returns -1 if no ttl, 0 if exceeded, 1 if ok */ int checkttl(struct radmsg *msg, uint32_t *attrtype) { uint8_t alen, *subattrs; struct tlv *attr; struct list_node *node; uint32_t vendor; int sublen; if (attrtype[1] == 256) { /* not vendor */ attr = radmsg_gettype(msg, attrtype[0]); if (attr) return decttl(attr->l, attr->v); } else for (node = list_first(msg->attrs); node; node = list_next(node)) { attr = (struct tlv *)node->data; if (attr->t != RAD_Attr_Vendor_Specific || attr->l <= 4) continue; memcpy(&vendor, attr->v, 4); if (ntohl(vendor) != attrtype[0]) continue; sublen = attr->l - 4; subattrs = attr->v + 4; if (!attrvalidate(subattrs, sublen)) continue; while (sublen > 1) { if (ATTRTYPE(subattrs) == attrtype[1]) return decttl(ATTRVALLEN(subattrs), ATTRVAL(subattrs)); alen = ATTRLEN(subattrs); sublen -= alen; subattrs += alen; } } return -1; } const char *radmsgtype2string(uint8_t code) { static const char *rad_msg_names[] = { "", "Access-Request", "Access-Accept", "Access-Reject", "Accounting-Request", "Accounting-Response", "", "", "", "", "", "Access-Challenge", "Status-Server", "Status-Client"}; return code < 14 && *rad_msg_names[code] ? rad_msg_names[code] : "Unknown"; } void char2hex(char *h, unsigned char c) { static const char hexdigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; h[0] = hexdigits[c / 16]; h[1] = hexdigits[c % 16]; return; } uint8_t *radattr2ascii(struct tlv *attr) { int i, l; uint8_t *a, *d; if (!attr) return NULL; l = attr->l; for (i = 0; i < attr->l; i++) if (attr->v[i] < 32 || attr->v[i] > 126) l += 2; if (l == attr->l) return (uint8_t *)stringcopy((char *)attr->v, attr->l); a = malloc(l + 1); if (!a) return NULL; d = a; for (i = 0; i < attr->l; i++) if (attr->v[i] < 32 || attr->v[i] > 126) { *d++ = '%'; char2hex((char *)d, attr->v[i]); d += 2; } else *d++ = attr->v[i]; *d = '\0'; return a; } void replylog(struct radmsg *msg, struct server *server, struct request *rq) { uint8_t *username, *logusername = NULL, *stationid, *replymsg, *tmpmsg; uint8_t *operatorname, *cui; char *servername; uint8_t level = DBG_NOTICE; char tmp[INET6_ADDRSTRLEN], logstationid[128] = {0}; servername = server ? server->conf->name : "_self_"; username = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_User_Name)); if (username) { logusername = options.logfullusername ? username : (uint8_t *)strchr((char *)username, '@'); } stationid = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Calling_Station_Id)); if (stationid) { sprintf((char *)logstationid, " stationid "); switch (options.log_mac) { case RSP_MAC_VENDOR_HASHED: case RSP_MAC_VENDOR_KEY_HASHED: memcpy(logstationid + 11, stationid, 9); fticks_hashmac((uint8_t *)stationid, options.log_mac == RSP_MAC_VENDOR_KEY_HASHED ? options.log_key : NULL, 65, (uint8_t *)logstationid + 20); break; case RSP_MAC_FULLY_HASHED: case RSP_MAC_FULLY_KEY_HASHED: fticks_hashmac((uint8_t *)stationid, options.log_mac == RSP_MAC_FULLY_KEY_HASHED ? options.log_key : NULL, 65, (uint8_t *)logstationid + 11); break; case RSP_MAC_STATIC: sprintf(logstationid + 11, "undisclosed"); break; case RSP_MAC_ORIGINAL: default: strncpy(logstationid + 11, (char *)stationid, 128 - 12); } free(stationid); } cui = radattr2ascii(radmsg_gettype(msg, RAD_Attr_CUI)); if (cui) { if (asprintf((char **)&tmpmsg, " cui %s", cui) >= 0) { free(cui); cui = tmpmsg; } } operatorname = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Operator_Name)); if (operatorname) { if (asprintf((char **)&tmpmsg, " operator %s", operatorname) >= 0) { free(operatorname); operatorname = tmpmsg; } } replymsg = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Reply_Message)); if (replymsg) { if (asprintf((char **)&tmpmsg, " (%s)", replymsg) >= 0) { free(replymsg); replymsg = tmpmsg; } } if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Accounting_Response) { if (msg->code == RAD_Accounting_Response) level = DBG_INFO; if (logusername) { debug(level, "%s for user %s%s%s from %s%s to %s (%s)%s", radmsgtype2string(msg->code), logusername, logstationid, cui ? (char *)cui : "", servername, replymsg ? (char *)replymsg : "", rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp)), operatorname ? (char *)operatorname : ""); } else { debug(level, "%s (response to %s) from %s to %s (%s)", radmsgtype2string(msg->code), radmsgtype2string(rq->msg->code), servername, rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp))); } } else if (msg->code == RAD_Access_Request) { debug(level, "missing response to %s for user %s%s from %s (%s) to %s", radmsgtype2string(msg->code), logusername, logstationid, rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp)), servername); } free(username); free(cui); free(operatorname); free(replymsg); } void respond(struct request *rq, uint8_t code, struct tlv *addattr, int add_msg_auth) { struct radmsg *msg; struct tlv *attr; char tmp[INET6_ADDRSTRLEN]; msg = radmsg_init(code, rq->msg->id, rq->msg->auth); if (!msg) { debug(DBG_ERR, "respond: malloc failed"); goto errexit; } if (add_msg_auth) { attr = maketlv(RAD_Attr_Message_Authenticator, 16, NULL); if (!attr || !radmsg_add(msg, attr, 1)) { freetlv(attr); debug(DBG_ERR, "respond: malloc failed"); goto errexit; } } if (addattr && !radmsg_add(msg, addattr, 0)) { debug(DBG_ERR, "respond: malloc failed"); goto errexit; } if (radmsg_copy_attrs(msg, rq->msg, RAD_Attr_Proxy_State) < 0) debug(DBG_ERR, "respond: unable to copy all Proxy-State attributes"); replylog(msg, NULL, rq); debug(DBG_DBG, "respond: sending %s (id %d) to %s (%s)", radmsgtype2string(msg->code), msg->id, rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp))); radmsg_free(rq->msg); rq->msg = msg; sendreply(newrqref(rq)); return; errexit: radmsg_free(msg); freetlv(addattr); } struct clsrvconf *choosesrvconf(struct list *srvconfs) { struct list_node *entry; struct clsrvconf *server, *best = NULL, *first = NULL; uint8_t bestlostrqs = MAX_LOSTRQS; for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { server = (struct clsrvconf *)entry->data; if (!server->servers) return server; pthread_mutex_lock(&server->servers->lock); if (server->servers->state == RSP_SERVER_STATE_FAILING) { pthread_mutex_unlock(&server->servers->lock); continue; } if (!first) first = server; if (server->servers->state == RSP_SERVER_STATE_STARTUP || server->servers->state == RSP_SERVER_STATE_RECONNECTING) { pthread_mutex_unlock(&server->servers->lock); continue; } if (!server->servers->lostrqs) { pthread_mutex_unlock(&server->servers->lock); return server; } if (!best) { best = server; bestlostrqs = server->servers->lostrqs; pthread_mutex_unlock(&server->servers->lock); continue; } if (server->servers->lostrqs < bestlostrqs) best = server; pthread_mutex_unlock(&server->servers->lock); } /* if the best server has max lost requests, any other selectable server has too. To give * everyone another chance for selection by reducing lost requests. */ if (best && bestlostrqs >= MAX_LOSTRQS) for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { pthread_mutex_lock(&((struct clsrvconf *)entry->data)->servers->lock); if (((struct clsrvconf *)entry->data)->servers->lostrqs >= MAX_LOSTRQS) ((struct clsrvconf *)entry->data)->servers->lostrqs = MAX_LOSTRQS - 1; pthread_mutex_unlock(&((struct clsrvconf *)entry->data)->servers->lock); } return best ? best : first; } /* returns with lock on realm, protects from server changes while in use by radsrv/sendrq */ struct server *findserver(struct realm **realm, struct tlv *username, uint8_t acc) { struct clsrvconf *srvconf; struct realm *subrealm; struct server *server = NULL; char *id = (char *)tlv2str(username); if (!id) return NULL; /* returns with lock on realm */ *realm = id2realm(realms, id); if (!*realm) goto exit; debug(DBG_DBG, "found matching realm: %s", (*realm)->name); srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs); if (srvconf && !(*realm)->parent && !srvconf->servers && srvconf->dynamiclookupcommand) { subrealm = adddynamicrealmserver(*realm, id); if (subrealm) { pthread_mutex_lock(&subrealm->mutex); pthread_mutex_unlock(&(*realm)->mutex); freerealm(*realm); *realm = subrealm; debug(DBG_DBG, "added realm: %s", (*realm)->name); srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs); debug(DBG_DBG, "found conf for new realm: %s", srvconf->name); } } else if (srvconf && !srvconf->servers && srvconf->dynamiclookupcommand) { if (addserver(srvconf, (*realm)->name)) { srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs); debug(DBG_DBG, "found conf for realm: %s", srvconf->name); } } if (srvconf) { debug(DBG_DBG, "found matching conf: %s", srvconf->name); server = srvconf->servers; } exit: free(id); return server; } struct request *newrequest(void) { struct request *rq; rq = malloc(sizeof(struct request)); if (!rq) { debug(DBG_ERR, "newrequest: malloc failed"); return NULL; } memset(rq, 0, sizeof(struct request)); rq->refcount = 1; pthread_mutex_init(&rq->refmutex, NULL); gettimeofday(&rq->created, NULL); return rq; } static void purgedupcache(struct client *client) { struct request *r; struct timeval now; int i; gettimeofday(&now, NULL); for (i = 0; i < MAX_REQUESTS; i++) { r = client->rqs[i]; if (r && now.tv_sec - r->created.tv_sec > r->from->conf->dupinterval) { removeclientrq(client, i); } } } int addclientrq(struct request *rq) { struct request *r; struct timeval now; char tmp[INET6_ADDRSTRLEN]; r = rq->from->rqs[rq->rqid]; if (r) { if (!memcmp(rq->rqauth, r->rqauth, 16)) { gettimeofday(&now, NULL); if (now.tv_sec - r->created.tv_sec < r->from->conf->dupinterval) { if (r->replybuf) { debug(DBG_INFO, "addclientrq: already sent reply to request with id %d from %s, resending", rq->rqid, addr2string(r->from->addr, tmp, sizeof(tmp))); sendreply(newrqref(r)); } else debug(DBG_INFO, "addclientrq: already got request with id %d from %s, ignoring", rq->rqid, addr2string(r->from->addr, tmp, sizeof(tmp))); return 0; } } removeclientrq(rq->from, rq->rqid); } rq->from->rqs[rq->rqid] = newrqref(rq); return 1; } void rmclientrq(struct request *rq, uint8_t id) { struct request *r; r = rq->from->rqs[id]; if (r) { rq->from->rqs[id] = NULL; rq->from = NULL; freerq(r); } } static void log_accounting_resp(struct client *from, struct radmsg *msg, char *user) { char tmp[INET6_ADDRSTRLEN]; const char *status_type = attrval2strdict(radmsg_gettype(msg, RAD_Attr_Acct_Status_Type)); char *nas_ip_address = tlv2ipv4addr(radmsg_gettype(msg, RAD_Attr_NAS_IP_Address)); char *framed_ip_address = tlv2ipv4addr(radmsg_gettype(msg, RAD_Attr_Framed_IP_Address)); time_t event_timestamp_i = tlv2longint(radmsg_gettype(msg, RAD_Attr_Event_Timestamp)); char event_timestamp[32]; /* timestamp should be at most 21 bytes, leave a few spare */ uint8_t *session_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Acct_Session_Id)); uint8_t *called_station_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Called_Station_Id)); uint8_t *calling_station_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Calling_Station_Id)); const char *terminate_cause = attrval2strdict(radmsg_gettype(msg, RAD_Attr_Acct_Terminate_Cause)); strftime(event_timestamp, sizeof(event_timestamp), "%FT%TZ", gmtime(&event_timestamp_i)); debug(DBG_NOTICE, "Accounting %s (id %d) at %s from client %s (%s): { SID=%s, User-Name=%s, Ced-S-Id=%s, Cing-S-Id=%s, NAS-IP=%s, Framed-IP=%s, Sess-Time=%u, In-Packets=%u, In-Octets=%u, Out-Packets=%u, Out-Octets=%u, Terminate-Cause=%s }", status_type ? status_type : "UNKNOWN", msg->id, event_timestamp_i ? event_timestamp : "UNKNOWN", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), session_id ? session_id : (uint8_t *)"", user, called_station_id ? called_station_id : (uint8_t *)"", calling_station_id ? calling_station_id : (uint8_t *)"", nas_ip_address ? nas_ip_address : "0.0.0.0", framed_ip_address ? framed_ip_address : "0.0.0.0", tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Session_Time)), tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Input_Packets)), tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Input_Octets)), tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Output_Packets)), tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Output_Octets)), terminate_cause ? terminate_cause : ""); free(framed_ip_address); free(nas_ip_address); free(session_id); free(called_station_id); free(calling_station_id); } /** * @brief ensure msg contains a message-authenticator as the first attrbute * * @param msg * @return 1 if ok, 0 if failed (i.e. memory allocation error) */ static int ensuremsgauthfront(struct radmsg *msg) { static uint8_t msgauth[] = {RAD_Attr_Message_Authenticator, 0}; dorewriterm(msg, msgauth, NULL, 0); if (!radmsg_add(msg, maketlv(RAD_Attr_Message_Authenticator, 16, NULL), 1)) { debug(DBG_WARN, "ensuremsgauthfront: failed to add message-authenticator"); return 0; } return 1; } /* Called from server readers, handling incoming requests from * clients. */ /* returns 0 if validation/authentication fails, else 1 */ int radsrv(struct request *rq) { struct radmsg *msg = NULL; struct tlv *attr; uint8_t *userascii = NULL; struct realm *realm = NULL; struct server *to = NULL; struct client *from = rq->from; int ttlres; char tmp[INET6_ADDRSTRLEN]; msg = buf2radmsg(rq->buf, rq->buflen, from->conf->secret, from->conf->secret_len, NULL); memset(rq->buf, 0, rq->buflen); free(rq->buf); rq->buf = NULL; if (!msg || msg->msgauthinvalid) { debug(DBG_WARN, "radsrv: ignoring request from %s (%s), message-authenticator invalid.", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp))); radmsg_free(msg); freerq(rq); return 0; } rq->msg = msg; rq->rqid = msg->id; memcpy(rq->rqauth, msg->auth, 16); debug(DBG_DBG, "radsrv: code %d, id %d", msg->code, msg->id); if (msg->code == RAD_Disconnect_Request) { debug(DBG_INFO, "radsrv: disconnect-request not supported"); respond(rq, RAD_Disconnect_NAK, maketlv(RAD_Attr_Error_Cause, sizeof(RAD_Err_Unsupported_Extension), &(int){RAD_Err_Unsupported_Extension}), 1); } if (msg->code == RAD_CoA_Request) { debug(DBG_INFO, "radsrv: CoA-request not supported"); respond(rq, RAD_CoA_NAK, maketlv(RAD_Attr_Error_Cause, sizeof(RAD_Err_Unsupported_Extension), &(int){RAD_Err_Unsupported_Extension}), 1); } if (msg->code != RAD_Access_Request && msg->code != RAD_Status_Server && msg->code != RAD_Accounting_Request) { debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring"); goto exit; } purgedupcache(from); if (!addclientrq(rq)) goto exit; if (msg->code == RAD_Status_Server) { respond(rq, RAD_Access_Accept, NULL, 1); goto exit; } /* below: code == RAD_Access_Request || code == RAD_Accounting_Request */ if ((from->conf->reqmsgauth || from->conf->reqmsgauthproxy) && (from->conf->type == RAD_UDP || from->conf->type == RAD_TCP) && msg->code == RAD_Access_Request) { if (radmsg_gettype(msg, RAD_Attr_Message_Authenticator) == NULL && (from->conf->reqmsgauth || (from->conf->reqmsgauthproxy && radmsg_gettype(msg, RAD_Attr_Proxy_State) != NULL))) { debug(DBG_INFO, "radsrv: ignoring request from client %s (%s), missing required message-authenticator", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp))); goto exit; } } if (options.verifyeap && msg->code == RAD_Access_Request && !verifyeapformat(msg)) { debug(DBG_WARN, "radsrv: eap format error, forcing access-reject"); respond(rq, RAD_Access_Reject, NULL, 1); goto exit; } if (from->conf->rewritein && !dorewrite(msg, from->conf->rewritein)) goto rmclrqexit; ttlres = checkttl(msg, options.ttlattrtype); if (!ttlres) { debug(DBG_INFO, "radsrv: ignoring request from client %s (%s), ttl exceeded", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp))); goto exit; } attr = radmsg_gettype(msg, RAD_Attr_User_Name); if (!attr) { if (msg->code == RAD_Accounting_Request) { respond(rq, RAD_Accounting_Response, NULL, 0); } else debug(DBG_INFO, "radsrv: ignoring access request, no username attribute"); goto exit; } if (from->conf->rewriteusername && !rewriteusername(rq, attr)) { debug(DBG_WARN, "radsrv: username malloc failed, ignoring request"); goto rmclrqexit; } userascii = radattr2ascii(attr); if (!userascii) goto rmclrqexit; debug(DBG_INFO, "radsrv: got %s (id %d) with username: %s from client %s (%s)", radmsgtype2string(msg->code), msg->id, userascii, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp))); /* will return with lock on the realm */ to = findserver(&realm, attr, msg->code == RAD_Accounting_Request); if (!realm) { debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it"); goto exit; } if (!to) { if (realm->message && msg->code == RAD_Access_Request) { respond(rq, RAD_Access_Reject, maketlv(RAD_Attr_Reply_Message, strlen(realm->message), realm->message), 1); } else if (realm->accresp && msg->code == RAD_Accounting_Request) { if (realm->acclog) log_accounting_resp(from, msg, (char *)userascii); respond(rq, RAD_Accounting_Response, NULL, 0); } goto exit; } if ((to->conf->loopprevention == 1 || (to->conf->loopprevention == UCHAR_MAX && options.loopprevention == 1)) && !strcmp(from->conf->name, to->conf->name)) { debug(DBG_INFO, "radsrv: Loop prevented, not forwarding request from client %s (%s) to server %s, discarding", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), to->conf->name); goto exit; } /* If there is a CHAP-Password attribute but no CHAP-Challenge * one, create a CHAP-Challenge containing the Request * Authenticator because that's what the CHAP-Password is based * on. */ attr = radmsg_gettype(msg, RAD_Attr_CHAP_Password); if (attr) { debug(DBG_DBG, "%s: found CHAP-Password with value length %d", __func__, attr->l); attr = radmsg_gettype(msg, RAD_Attr_CHAP_Challenge); if (attr == NULL) { debug(DBG_DBG, "%s: no CHAP-Challenge found, creating one", __func__); attr = maketlv(RAD_Attr_CHAP_Challenge, 16, msg->auth); if (attr == NULL || radmsg_add(msg, attr, 0) != 1) { debug(DBG_ERR, "%s: adding CHAP-Challenge failed, " "CHAP-Password request dropped", __func__); freetlv(attr); goto rmclrqexit; } } } /* Create new Request Authenticator. */ if (msg->code == RAD_Accounting_Request) memset(msg->auth, 0, 16); else if (!RAND_bytes(msg->auth, 16)) { debug(DBG_WARN, "radsrv: failed to generate random auth"); goto rmclrqexit; } #ifdef DEBUG printfchars(NULL, "auth", "%02x ", msg->auth, 16); #endif attr = radmsg_gettype(msg, RAD_Attr_User_Password); if (attr) { debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", attr->l); if (!pwdrecrypt(attr->v, attr->l, from->conf->secret, from->conf->secret_len, to->conf->secret, to->conf->secret_len, rq->rqauth, msg->auth, NULL, 0, NULL, 0)) goto rmclrqexit; } if (to->conf->rewriteout && !dorewrite(msg, to->conf->rewriteout)) goto rmclrqexit; if (msg->code == RAD_Access_Request && !ensuremsgauthfront(msg)) goto rmclrqexit; if (ttlres == -1 && (options.addttl || to->conf->addttl)) addttlattr(msg, options.ttlattrtype, to->conf->addttl ? to->conf->addttl : options.addttl); free(userascii); rq->to = to; sendrq(rq); pthread_mutex_unlock(&realm->mutex); freerealm(realm); return 1; rmclrqexit: rmclientrq(rq, msg->id); exit: freerq(rq); free(userascii); if (realm) { pthread_mutex_unlock(&realm->mutex); freerealm(realm); } return 1; } /** Called from client readers if waiting for packets times out * return 0 if client should continue waiting * 1 if client should close the connection and exit */ int timeouth(struct server *server) { uint8_t unresponsive = 0; struct timeval now; pthread_mutex_lock(&server->lock); unresponsive = server->lostrqs && server->conf->statusserver != RSP_STATSRV_OFF; pthread_mutex_unlock(&server->lock); if (unresponsive) { debug(DBG_WARN, "timeouth: server %s did not respond to status server, closing connection.", server->conf->name); if (server->dynamiclookuparg) return 1; if (server->conf->pdef->connecter) server->conf->pdef->connecter(server, 0, 1); return 0; } else if (server->dynamiclookuparg) { gettimeofday(&now, NULL); if (now.tv_sec - server->lastreply.tv_sec > IDLE_TIMEOUT) { debug(DBG_INFO, "timeouth: idle timeout for server %s (%s)", server->conf->name, server->dynamiclookuparg); return 1; } } debug(DBG_DBG, "timeouth: continue waiting"); return 0; } /** Called from client readers if connection is lost * return 0 if client should retry receiving packets * 1 if client should clean up and exit */ int closeh(struct server *server) { debug(DBG_WARN, "closeh: connection to server %s lost", server->conf->name); if (!server->dynamiclookuparg && server->conf->pdef->connecter) { server->conf->pdef->connecter(server, 0, 1); return 0; } return 1; } /* Called from client readers, handling replies from servers. */ /* returns 0 if validation/authentication fails, else 1 */ int replyh(struct server *server, uint8_t *buf, int len) { struct client *from; struct rqout *rqout; int sublen, ttlres; unsigned char *subattrs; struct radmsg *msg = NULL; struct tlv *attr; struct list_node *node; char tmp[INET6_ADDRSTRLEN]; pthread_mutex_lock(&server->lock); server->lostrqs = 0; pthread_mutex_unlock(&server->lock); rqout = server->requests + buf[1]; pthread_mutex_lock(rqout->lock); msg = buf2radmsg(buf, len, server->conf->secret, server->conf->secret_len, rqout->rq ? rqout->rq->msg->auth : NULL); memset(buf, 0, len); free(buf); buf = NULL; if (!msg) { debug(DBG_NOTICE, "replyh: message decode/validation error from server %s", server->conf->name); pthread_mutex_unlock(rqout->lock); return 0; } if (msg->code != RAD_Access_Accept && msg->code != RAD_Access_Reject && msg->code != RAD_Access_Challenge && msg->code != RAD_Accounting_Response) { debug(DBG_INFO, "replyh: discarding message type %s, accepting only access accept, access reject, access challenge and accounting response messages", radmsgtype2string(msg->code)); goto errunlock; } if (!rqout->tries || !rqout->rq) { debug(DBG_INFO, "replyh: no outstanding request with this id (%d) from server %s, ignoring reply", msg->id, server->conf->name); goto errunlock; } if (msg->msgauthinvalid) { debug(DBG_WARN, "replyh: message-authenticator invalid from server %s", server->conf->name); radmsg_free(msg); pthread_mutex_unlock(rqout->lock); return 0; } if (server->conf->reqmsgauth && (server->conf->type == RAD_UDP || server->conf->type == RAD_TCP) && (msg->code == RAD_Access_Challenge || msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject)) { if (radmsg_gettype(msg, RAD_Attr_Message_Authenticator) == NULL) { debug(DBG_NOTICE, "replyh: discarding %s (id %d) from %s, missing message-authenticator", radmsgtype2string(msg->code), msg->id, server->conf->name); goto errunlock; } } debug(DBG_DBG, "got %s message with id %d", radmsgtype2string(msg->code), msg->id); gettimeofday(&server->lastrcv, NULL); if (rqout->rq->msg->code == RAD_Status_Server) { freerqoutdata(rqout); debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); if (server->conf->statusserver == RSP_STATSRV_AUTO) server->conf->statusserver = RSP_STATSRV_MINIMAL; goto errunlock; } gettimeofday(&server->lastreply, NULL); if (server->conf->rewritein && !dorewrite(msg, server->conf->rewritein)) { debug(DBG_INFO, "replyh: rewritein failed"); goto errunlock; } ttlres = checkttl(msg, options.ttlattrtype); if (!ttlres) { debug(DBG_INFO, "replyh: ignoring reply from server %s, ttl exceeded", server->conf->name); goto errunlock; } from = rqout->rq->from; /* MS MPPE */ for (node = list_first(msg->attrs); node; node = list_next(node)) { attr = (struct tlv *)node->data; if (attr->t != RAD_Attr_Vendor_Specific) continue; if (attr->l <= 4) break; if (attr->v[0] != 0 || attr->v[1] != 0 || attr->v[2] != 1 || attr->v[3] != 55) /* 311 == MS */ continue; sublen = attr->l - 4; subattrs = attr->v + 4; if (!attrvalidate(subattrs, sublen) || !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key", rqout->rq, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len) || !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key", rqout->rq, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len)) break; } if (node) { debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply"); goto errunlock; } /* reencrypt tunnel-password RFC2868 */ attr = radmsg_gettype(msg, RAD_Attr_Tunnel_Password); if (attr && msg->code == RAD_Access_Accept) { uint8_t newsalt[2]; debug(DBG_DBG, "replyh: found tunnelpwdattr with value length %d", attr->l); if (!RAND_bytes(newsalt, 2)) goto errunlock; newsalt[0] |= 0x80; if (!pwdrecrypt(attr->v + 3, attr->l - 3, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len, rqout->rq->msg->auth, rqout->rq->rqauth, attr->v + 1, 2, newsalt, 2)) goto errunlock; memcpy(attr->v + 1, newsalt, 2); } replylog(msg, server, rqout->rq); if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject) if (options.fticks_reporting && from->conf->fticks_viscountry != NULL) fticks_log(&options, from, msg, rqout->rq); msg->id = (char)rqout->rq->rqid; memcpy(msg->auth, rqout->rq->rqauth, 16); if (rqout->rq->origusername && (attr = radmsg_gettype(msg, RAD_Attr_User_Name))) { if (!resizeattr(attr, strlen(rqout->rq->origusername))) { debug(DBG_WARN, "replyh: malloc failed, ignoring reply"); goto errunlock; } memcpy(attr->v, rqout->rq->origusername, strlen(rqout->rq->origusername)); } if (from->conf->rewriteout && !dorewrite(msg, from->conf->rewriteout)) { debug(DBG_WARN, "replyh: rewriteout failed"); goto errunlock; } if ((msg->code == RAD_Access_Challenge || msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject) && !ensuremsgauthfront(msg)) goto errunlock; if (ttlres == -1 && (options.addttl || from->conf->addttl)) addttlattr(msg, options.ttlattrtype, from->conf->addttl ? from->conf->addttl : options.addttl); debug(DBG_DBG, "replyh: passing %s (id %d) to client %s (%s)", radmsgtype2string(msg->code), msg->id, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp))); radmsg_free(rqout->rq->msg); rqout->rq->msg = msg; sendreply(newrqref(rqout->rq)); freerqoutdata(rqout); pthread_mutex_unlock(rqout->lock); return 1; errunlock: radmsg_free(msg); pthread_mutex_unlock(rqout->lock); return 1; } struct request *createstatsrvrq(void) { struct request *rq; struct tlv *attr; rq = newrequest(); if (!rq) return NULL; rq->msg = radmsg_init(RAD_Status_Server, 0, NULL); if (!rq->msg) goto exit; attr = maketlv(RAD_Attr_Message_Authenticator, 16, NULL); if (!attr) goto exit; if (!radmsg_add(rq->msg, attr, 1)) { freetlv(attr); goto exit; } return rq; exit: freerq(rq); return NULL; } static void incrementlostrqs(struct server *server) { pthread_mutex_lock(&server->lock); if (server->lostrqs < MAX_LOSTRQS) server->lostrqs++; pthread_mutex_unlock(&server->lock); } /* code for removing state not finished */ void *clientwr(void *arg) { struct server *server = (struct server *)arg; struct rqout *rqout = NULL; pthread_t clientrdth; int i; time_t secs; uint8_t rnd, do_resend = 0, statusserver_requested = 0; struct timeval now, laststatsrv; struct timespec timeout; struct request *statsrvrq; struct clsrvconf *conf; assert(server); conf = server->conf; #define ZZZ 900 if (server->state != RSP_SERVER_STATE_BLOCKING_STARTUP) server->state = RSP_SERVER_STATE_STARTUP; if (!conf->hostports && server->dynamiclookuparg && !dynamicconfig(server)) { server->state = RSP_SERVER_STATE_FAILING; debug(DBG_WARN, "%s: dynamicconfig(%s: %s) failed, Not trying again for %ds", __func__, server->conf->name, server->dynamiclookuparg, ZZZ); goto errexitwait; } /* FIXME: Is resolving not always done by compileserverconfig(), * either as part of static configuration setup or by * dynamicconfig() above? */ if (!resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) { debug(DBG_WARN, "%s: resolve failed, Not trying again for %ds", __func__, ZZZ); server->state = RSP_SERVER_STATE_FAILING; goto errexitwait; } memset(&timeout, 0, sizeof(struct timespec)); gettimeofday(&server->lastreply, NULL); server->lastrcv = server->lastreply; laststatsrv = server->lastreply; if (conf->pdef->connecter) { if (!conf->pdef->connecter(server, server->dynamiclookuparg ? 5 : 0, 0)) { server->state = RSP_SERVER_STATE_FAILING; if (server->dynamiclookuparg) { debug(DBG_WARN, "%s: connect failed, giving up. Not trying again for %ds", __func__, ZZZ); goto errexitwait; } goto errexit; } if (pthread_create(&clientrdth, &pthread_attr, conf->pdef->clientconnreader, (void *)server)) { debugerrno(errno, DBG_ERR, "clientwr: pthread_create failed"); server->state = RSP_SERVER_STATE_FAILING; goto errexit; } } server->state = RSP_SERVER_STATE_CONNECTED; for (;;) { pthread_mutex_lock(&server->newrq_mutex); if (!server->newrq) { gettimeofday(&now, NULL); /* random 0-7 seconds */ RAND_bytes(&rnd, 1); rnd /= 32; if (conf->statusserver != RSP_STATSRV_OFF) { secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; if (now.tv_sec - secs > STATUS_SERVER_PERIOD) secs = now.tv_sec; if (!timeout.tv_sec || timeout.tv_sec > secs + STATUS_SERVER_PERIOD + rnd) timeout.tv_sec = secs + STATUS_SERVER_PERIOD + rnd; } else { if (!timeout.tv_sec || timeout.tv_sec > now.tv_sec + STATUS_SERVER_PERIOD + rnd) timeout.tv_sec = now.tv_sec + STATUS_SERVER_PERIOD + rnd; } #if 0 if (timeout.tv_sec > now.tv_sec) debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec); #endif pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout); timeout.tv_sec = 0; } if (server->newrq) { debug(DBG_DBG, "clientwr: got new request"); server->newrq = 0; } if (server->conreset) { debug(DBG_DBG, "clientwr: connection reset; resending all outstanding requests"); do_resend = 1; server->conreset = 0; gettimeofday(&server->lastrcv, NULL); } #if 0 else debug(DBG_DBG, "clientwr: request timer expired, processing request queue"); #endif pthread_mutex_unlock(&server->newrq_mutex); if (do_resend || server->lastrcv.tv_sec > laststatsrv.tv_sec) statusserver_requested = 0; for (i = 0; i < MAX_REQUESTS; i++) { if (server->clientrdgone) { server->state = RSP_SERVER_STATE_FAILING; if (conf->pdef->connecter) pthread_join(clientrdth, NULL); goto errexit; } for (; i < MAX_REQUESTS; i++) { rqout = server->requests + i; if (rqout->rq) { pthread_mutex_lock(rqout->lock); if (rqout->rq) break; pthread_mutex_unlock(rqout->lock); } } if (i == MAX_REQUESTS) break; gettimeofday(&now, NULL); if (do_resend) { if (rqout->tries > 0) rqout->tries--; } else if (now.tv_sec < rqout->expiry.tv_sec) { if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec) timeout.tv_sec = rqout->expiry.tv_sec; pthread_mutex_unlock(rqout->lock); continue; } if (rqout->tries > 0 && now.tv_sec - server->lastrcv.tv_sec > conf->retryinterval && !do_resend) statusserver_requested = 1; if (do_resend && *rqout->rq->buf == RAD_Status_Server) { freerqoutdata(rqout); pthread_mutex_unlock(rqout->lock); continue; } if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) { debug(DBG_DBG, "clientwr: removing expired packet from queue"); replylog(rqout->rq->msg, server, rqout->rq); if (conf->statusserver == RSP_STATSRV_ON || conf->statusserver == RSP_STATSRV_MINIMAL) { if (*rqout->rq->buf == RAD_Status_Server) { debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); incrementlostrqs(server); } } else { if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) { if (server->lastreply.tv_sec >= laststatsrv.tv_sec) { debug(DBG_DBG, "clientwr: status server autodetect failed, disabling status server for %s", conf->name); conf->statusserver = RSP_STATSRV_OFF; } } else { debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); incrementlostrqs(server); } } freerqoutdata(rqout); pthread_mutex_unlock(rqout->lock); continue; } rqout->expiry.tv_sec = now.tv_sec + conf->retryinterval; if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec) timeout.tv_sec = rqout->expiry.tv_sec; rqout->tries++; if (!conf->pdef->clientradput(server, rqout->rq->buf, rqout->rq->buflen)) { debug(DBG_WARN, "clientwr: could not send request to server %s", conf->name); incrementlostrqs(server); } pthread_mutex_unlock(rqout->lock); } do_resend = 0; if (server->state == RSP_SERVER_STATE_CONNECTED && !(conf->statusserver == RSP_STATSRV_OFF)) { gettimeofday(&now, NULL); if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - (server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec) > STATUS_SERVER_PERIOD) || ((conf->statusserver == RSP_STATSRV_MINIMAL || conf->statusserver == RSP_STATSRV_ON) && statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD) || (conf->statusserver == RSP_STATSRV_AUTO && server->lastreply.tv_sec >= laststatsrv.tv_sec)) { laststatsrv = now; statsrvrq = createstatsrvrq(); if (statsrvrq) { statsrvrq->to = server; debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name); sendrq(statsrvrq); } statusserver_requested = 0; } } } errexitwait: /* flush request queue so we don't block incoming retries by removing blocked duplicates*/ for (i = 0; i < MAX_REQUESTS; i++) { rqout = server->requests + i; pthread_mutex_lock(rqout->lock); if (rqout->rq) rmclientrq(rqout->rq, rqout->rq->rqid); freerqoutdata(rqout); pthread_mutex_unlock(rqout->lock); } sleep(ZZZ); errexit: debug(DBG_DBG, "clientwr: server %s (%s) finished, cleaning up", server->conf->name, server->dynamiclookuparg ? server->dynamiclookuparg : "static"); if (server->dynamiclookuparg) { removeserversubrealms(realms, conf); freeclsrvconf(conf); } freeserver(server, 1); return NULL; } void createlistener(uint8_t type, char *arg) { pthread_t th; struct addrinfo *res; int s = -1, on = 1, *sp = NULL; struct hostportres *hp = newhostport(arg, protodefs[type]->portdefault, 0); char tmp[INET6_ADDRSTRLEN]; if (!hp || !resolvehostport(hp, AF_UNSPEC, protodefs[type]->socktype, 1)) debugx(1, DBG_ERR, "createlistener: failed to resolve %s", arg); for (res = hp->addrinfo; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { debugerrno(errno, DBG_WARN, "createlistener: socket failed"); continue; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: SO_REUSEADDR"); disable_DF_bit(s, res); #ifdef IPV6_V6ONLY if (res->ai_family == AF_INET6) if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: IPV6_V6ONLY"); #endif if (res->ai_socktype == SOCK_DGRAM) { if (res->ai_family == AF_INET6) { if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "craetelistener: IPV6_RECVPKTINFO"); } else if (res->ai_family == AF_INET) { #if defined(IP_PKTINFO) if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: IP_PKTINFO"); #elif defined(IP_RECVDSTADDR) if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: IP_RECVDSTADDR"); #endif } } if (bind(s, res->ai_addr, res->ai_addrlen)) { debugerrno(errno, DBG_WARN, "createlistener: bind to address %s failed", addr2string(res->ai_addr, tmp, sizeof(tmp))); close(s); continue; } sp = malloc(sizeof(int)); if (!sp) debugx(1, DBG_ERR, "malloc failed"); *sp = s; if (pthread_create(&th, &pthread_attr, protodefs[type]->listener, (void *)sp)) debugerrnox(errno, DBG_ERR, "pthread_create failed"); pthread_detach(th); } if (!sp) debugx(1, DBG_ERR, "createlistener: socket/bind failed"); debug(DBG_WARN, "createlistener: listening for %s on %s:%s", protodefs[type]->name, hp->host ? hp->host : "*", hp->port); freehostport(hp); } void createlisteners(uint8_t type) { int i; char **args; args = protodefs[type]->getlistenerargs(); if (args) for (i = 0; args[i]; i++) createlistener(type, args[i]); else createlistener(type, NULL); } void randinit(void) { time_t t; pid_t pid; while (!RAND_status()) { t = time(NULL); pid = getpid(); RAND_seed((unsigned char *)&t, sizeof(time_t)); RAND_seed((unsigned char *)&pid, sizeof(pid)); } } struct list *addsrvconfs(char *value, char **names) { struct list *conflist; int n; struct list_node *entry; struct clsrvconf *conf = NULL; if (!names || !*names) return NULL; conflist = list_create(); if (!conflist) { debug(DBG_ERR, "malloc failed"); return NULL; } for (n = 0; names[n]; n++) { for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; if (!strcasecmp(names[n], conf->name)) break; } if (!entry) { debug(DBG_ERR, "addsrvconfs failed for realm %s, no server named %s", value, names[n]); list_free(conflist); return NULL; } if (!list_push(conflist, conf)) { debug(DBG_ERR, "malloc failed"); list_free(conflist); return NULL; } debug(DBG_DBG, "addsrvconfs: added server %s for realm %s", conf->name, value); } return conflist; } void freerealm(struct realm *realm) { if (!realm) return; debug(DBG_DBG, "freerealm: called with refcount %d", realm->refcount); pthread_mutex_lock(&realm->refmutex); if (--realm->refcount) { pthread_mutex_unlock(&realm->refmutex); return; } pthread_mutex_unlock(&realm->refmutex); free(realm->name); free(realm->message); regfree(&realm->regex); pthread_mutex_destroy(&realm->refmutex); pthread_mutex_destroy(&realm->mutex); /* if refcount == 0, all subrealms gone */ list_destroy(realm->subrealms); /* if refcount == 0, all srvconfs gone */ list_destroy(realm->srvconfs); /* if refcount == 0, all accsrvconfs gone */ list_destroy(realm->accsrvconfs); freerealm(realm->parent); free(realm); } struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message, uint8_t accresp, uint8_t acclog) { int n; struct realm *realm; char *s, *regex = NULL; if (*value == '/') { /* regexp, remove optional trailing / if present */ if (value[strlen(value) - 1] == '/') value[strlen(value) - 1] = '\0'; } else { /* not a regexp, let us make it one */ if (*value == '*' && !value[1]) regex = stringcopy(".*", 0); else { for (n = 0, s = value; *s;) if (*s++ == '.') n++; regex = malloc(strlen(value) + n + 3); if (regex) { regex[0] = '@'; for (n = 1, s = value; *s; s++) { if (*s == '.') regex[n++] = '\\'; regex[n++] = *s; } regex[n++] = '$'; regex[n] = '\0'; } } if (!regex) { debug(DBG_ERR, "malloc failed"); realm = NULL; goto exit; } debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value); } realm = malloc(sizeof(struct realm)); if (!realm) { debug(DBG_ERR, "malloc failed"); goto exit; } memset(realm, 0, sizeof(struct realm)); if (pthread_mutex_init(&realm->mutex, NULL) || pthread_mutex_init(&realm->refmutex, NULL)) { debugerrno(errno, DBG_ERR, "mutex init failed"); free(realm); realm = NULL; goto exit; } newrealmref(realm); realm->name = stringcopy(value, 0); if (!realm->name) { debug(DBG_ERR, "malloc failed"); goto errexit; } if (message && strlen(message) > 253) { debug(DBG_ERR, "ReplyMessage can be at most 253 bytes"); goto errexit; } realm->message = message; realm->accresp = accresp; realm->acclog = acclog; if (regcomp(&realm->regex, regex ? regex : value + 1, REG_EXTENDED | REG_ICASE | REG_NOSUB)) { debug(DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1); goto errexit; } if (servers && *servers) { realm->srvconfs = addsrvconfs(value, servers); if (!realm->srvconfs) goto errexit; } if (accservers && *accservers) { realm->accsrvconfs = addsrvconfs(value, accservers); if (!realm->accsrvconfs) goto errexit; } if (!list_push(realmlist, realm)) { debug(DBG_ERR, "malloc failed"); pthread_mutex_destroy(&realm->mutex); goto errexit; } debug(DBG_DBG, "addrealm: added realm %s", value); goto exit; errexit: while (list_shift(realm->srvconfs)) ; while (list_shift(realm->accsrvconfs)) ; freerealm(realm); realm = NULL; exit: free(regex); if (servers) { if (realm) for (n = 0; servers[n]; n++) newrealmref(realm); freegconfmstr(servers); } if (accservers) { if (realm) for (n = 0; accservers[n]; n++) newrealmref(realm); freegconfmstr(accservers); } return realm; } struct list *createsubrealmservers(struct realm *realm, struct list *srvconfs) { struct list_node *entry; struct clsrvconf *conf, *srvconf; struct list *subrealmservers = NULL; if (list_first(srvconfs)) { subrealmservers = list_create(); if (!subrealmservers) return NULL; } for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; if (!conf->servers && conf->dynamiclookupcommand) { debug(DBG_DBG, "%s: copying config %s", __func__, conf->name); srvconf = shallowcloneserver(conf); if (!srvconf) continue; if (!addserver(srvconf, realm->name)) { freeclsrvconf(srvconf); continue; } conf = srvconf; } if (conf->servers) { if (list_push(subrealmservers, conf)) newrealmref(realm); else debug(DBG_ERR, "malloc failed"); } } return subrealmservers; } struct realm *adddynamicrealmserver(struct realm *realm, char *id) { struct realm *newrealm = NULL; char *realmname, *s; /* create dynamic for the realm (string after last @, exit if nothing after @ */ realmname = strrchr(id, '@'); if (!realmname) return NULL; realmname++; if (!*realmname) return NULL; for (s = realmname; *s; s++) if (*s != '.' && *s != '-' && !isalnum((int)*s)) return NULL; if (!realm->subrealms) realm->subrealms = list_create(); if (!realm->subrealms) return NULL; newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, stringcopy(realm->message, 0), realm->accresp, realm->acclog); if (!newrealm) { list_destroy(realm->subrealms); realm->subrealms = NULL; return NULL; } newrealm->parent = newrealmref(realm); /* add server and accserver to newrealm */ newrealm->srvconfs = createsubrealmservers(newrealm, realm->srvconfs); newrealm->accsrvconfs = createsubrealmservers(newrealm, realm->accsrvconfs); return newrealm; } int dynamicconfigexternal(struct server *server) { int ok = 0, fd[2], status; pid_t pid; struct clsrvconf *conf = server->conf; struct gconffile *cf = NULL; struct pollfd fds[1]; FILE *pipein; if (pipe(fd) > 0) { debugerrno(errno, DBG_ERR, "dynamicconfigexternal: pipe error"); return 0; } pid = fork(); if (pid < 0) { debugerrno(errno, DBG_ERR, "dynamicconfigexternal: fork error"); close(fd[0]); close(fd[1]); return 0; } else if (pid == 0) { /* child */ close(fd[0]); if (fd[1] != STDOUT_FILENO) { if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) debugx(1, DBG_ERR, "dynamicconfigexternal: dup2 error for command %s", conf->dynamiclookupcommand); close(fd[1]); } if (execlp(conf->dynamiclookupcommand, conf->dynamiclookupcommand, server->dynamiclookuparg, NULL) < 0) debugx(1, DBG_ERR, "dynamicconfigexternal: exec error for command %s", conf->dynamiclookupcommand); } close(fd[1]); pipein = fdopen(fd[0], "r"); fds[0].fd = fd[0]; fds[0].events = POLLIN; status = poll(fds, 1, 5000); if (status < 0) { debugerrno(errno, DBG_ERR, "dynamicconfigexternal: error while waiting for command output"); } else if (status == 0) { debug(DBG_WARN, "dynamicconfigexternal: command did not return anything in time"); kill(pid, SIGKILL); } else { pipein = pushgconffile(&cf, pipein, conf->dynamiclookupcommand); if (pipein) { ok = getgenericconfig(&cf, NULL, "Server", CONF_CBK, confserver_cb, (void *)conf, NULL); freegconf(&cf); pipein = NULL; } } if (pipein) fclose(pipein); if (waitpid(pid, &status, 0) < 0) { debugerrno(errno, DBG_ERR, "dynamicconfigexternal: wait error"); return 0; } if (status) { debug(DBG_INFO, "dynamicconfigexternal: command exited with status %d", WEXITSTATUS(status)); return 0; } return ok; } int dynamicconfigsrv(struct server *server, const char *srvstring) { struct clsrvconf *conf = server->conf; struct srv_record **srv; char **hostports; char *servername; int i, j, srvcount = 0, result = 0; debug(DBG_DBG, "dynamicconfigsrv: starting SRV lookup (%s) for %s", conf->dynamiclookupcommand, srvstring); srv = querysrv(srvstring, 2); if (!srv || !srv[0]) { debug(DBG_NOTICE, "dynamicconfigsrv: no SRV record for %s (%s)", server->dynamiclookuparg, srvstring); goto exitsrv; } /* sort srv records by priority, ascending; counting the entries as a sideeffect */ for (i = 1; srv[i]; i++) { struct srv_record *key = srv[i]; for (j = i - 1; j >= 0 && srv[j]->priority > key->priority; j--) srv[j + 1] = srv[j]; srv[j + 1] = key; } srvcount = i; hostports = calloc(srvcount + 1, sizeof(char *)); if (!hostports) { debug(DBG_ERR, "malloc failed"); goto exitsrv; } for (i = 0; srv[i]; i++) { char *hostport = malloc(strlen(srv[i]->host) + sizeof(":65535")); if (!hostport) { debug(DBG_ERR, "malloc failed"); goto exithostport; } sprintf(hostport, "%s:%d", srv[i]->host, srv[i]->port); hostports[i] = hostport; } servername = malloc(strlen("dynamic:") + strlen(server->dynamiclookuparg) + 1); if (!servername) { debug(DBG_ERR, "malloc failed"); goto exithostport; } sprintf(servername, "dynamic:%s", server->dynamiclookuparg); conf->name = servername; conf->hostsrc = hostports; if (!mergesrvconf(conf, NULL)) { goto exitservername; } result = compileserverconfig(conf, "dynamicconfig"); exitservername: free(servername); exithostport: freegconfmstr(hostports); exitsrv: freesrvresponse(srv); return result; } int dynamicconfignaptr(struct server *server) { int i, result = 0; struct naptr_record **naptr; debug(DBG_DBG, "dynamicconfignaptr: starting NAPTR lookup (%s) for %s", server->conf->dynamiclookupcommand, server->dynamiclookuparg); naptr = querynaptr(server->dynamiclookuparg, 2); if (!naptr) { debug(DBG_NOTICE, "dynamicconfignaptr: no NAPTR record for %s", server->dynamiclookuparg); return 0; } for (i = 0; naptr[i]; i++) { if (strcasecmp(strchr(server->conf->dynamiclookupcommand, ':') + 1, naptr[i]->services) == 0) { /* currently only the 'S' flag (perform SRV lookup) is supported */ if (strncasecmp(naptr[i]->flags, "S", sizeof("S")) != 0) continue; debug(DBG_DBG, "dynamicconfignaptr: found matching NAPTR record: %s", naptr[i]->replacement); result = dynamicconfigsrv(server, naptr[i]->replacement); break; } } freenaptrresponse(naptr); return result; } int dynamicconfig(struct server *server) { struct clsrvconf *conf = server->conf; char *srvquery, *srvext; int result = 0; debug(DBG_DBG, "dynamicconfig: need dynamic server config for %s", server->dynamiclookuparg); if (strncasecmp(conf->dynamiclookupcommand, "naptr:", sizeof("naptr:") - 1) == 0) { result = dynamicconfignaptr(server); } else if (strncasecmp(conf->dynamiclookupcommand, "srv:", sizeof("srv:") - 1) == 0) { srvext = strchr(conf->dynamiclookupcommand, ':'); if (!srvext) return 0; srvquery = malloc((strlen(srvext) + 1 + strlen(server->dynamiclookuparg) + 1) * sizeof(char)); if (!srvquery) return 0; sprintf(srvquery, "%s%s%s", srvext + 1, conf->dynamiclookupcommand[strlen(conf->dynamiclookupcommand) - 1] == '.' ? "" : ".", server->dynamiclookuparg); result = dynamicconfigsrv(server, srvquery); free(srvquery); } else { result = dynamicconfigexternal(server); } if (!result) debug(DBG_WARN, "dynamicconfig: failed to obtain dynamic server config for %s", server->dynamiclookuparg); else debug(DBG_NOTICE, "dynamicconfig: found dynamic server for realm %s", server->dynamiclookuparg); return result; } int setttlattr(struct options *opts, char *defaultattr) { char *ttlattr = opts->ttlattr ? opts->ttlattr : defaultattr; if (vattrname2val(ttlattr, opts->ttlattrtype, opts->ttlattrtype + 1) && (opts->ttlattrtype[1] != 256 || opts->ttlattrtype[0] < 256)) return 1; debug(DBG_ERR, "setttlattr: invalid TTLAttribute value %s", ttlattr); return 0; } void freeclsrvconf(struct clsrvconf *conf) { assert(conf); debug(DBG_DBG, "%s: freeing %p (%s)", __func__, conf, conf->name ? conf->name : "incomplete"); if (!conf->shallow) { #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) freegconfmstr(conf->confmatchcertattrs); freematchcertattr(conf); #endif free(conf->name); if (conf->hostsrc) freegconfmstr(conf->hostsrc); free(conf->portsrc); freegconfmstr(conf->source); free(conf->secret); free(conf->tls); free(conf->pskid); free(conf->pskkey); free(conf->confrewritein); free(conf->confrewriteout); free(conf->sniservername); free(conf->servername); if (conf->rewriteusername) { if (conf->rewriteusername->regex) regfree(conf->rewriteusername->regex); free(conf->rewriteusername->replacement); free(conf->rewriteusername); } free(conf->dynamiclookupcommand); conf->rewritein = NULL; conf->rewriteout = NULL; if (conf->hostports) freehostports(conf->hostports); if (conf->lock) { pthread_mutex_destroy(conf->lock); free(conf->lock); } /* not touching ssl_ctx, clients and servers */ } free(conf); } int mergeconfstring(char **dst, char **src) { char *t; if (src && *src) { *dst = *src; *src = NULL; return 1; } if (*dst) { t = stringcopy(*dst, 0); if (!t) { debug(DBG_ERR, "malloc failed"); return 0; } *dst = t; } return 1; } char **mstringcopy(char **in) { char **out; int n; if (!in) return NULL; for (n = 0; in[n];) n++; out = malloc((n + 1) * sizeof(char *)); if (!out) return NULL; for (n = 0; in[n]; n++) { out[n] = stringcopy(in[n], 0); if (!out[n]) { freegconfmstr(out); return NULL; } } out[n] = NULL; return out; } int mergeconfmstring(char ***dst, char ***src) { char **t; if (src && *src) { *dst = *src; *src = NULL; return 1; } if (*dst) { t = mstringcopy(*dst); if (!t) { debug(DBG_ERR, "malloc failed"); return 0; } *dst = t; } return 1; } /** * Merge config src into dst. * Assumes that dst is a shallow copy. All values defined in src are * moved to dst (no memory is duplicated, but pointers in src are set to NULL). * For NULL values in src the shallow data in dst is duplicated, resulting in a deep copy of dst. * If src is NULL, simply a deep copy of dst is created. * * @param dst the destination for the values * @param src the source for the values, or NULL * @return 1 if successful, 0 otherwise */ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) { if (!mergeconfstring(&dst->name, src ? &src->name : NULL) || !mergeconfmstring(&dst->hostsrc, src ? &src->hostsrc : NULL) || !mergeconfstring(&dst->portsrc, src ? &src->portsrc : NULL) || !mergeconfmstring(&dst->source, src ? &src->source : NULL) || !mergeconfstring((char **)&dst->secret, (char **)(src ? &src->secret : NULL)) || !mergeconfstring(&dst->tls, src ? &src->tls : NULL) || !mergeconfmstring(&dst->confmatchcertattrs, src ? &src->confmatchcertattrs : NULL) || !mergeconfstring(&dst->confrewritein, src ? &src->confrewritein : NULL) || !mergeconfstring(&dst->confrewriteout, src ? &src->confrewriteout : NULL) || !mergeconfstring(&dst->confrewriteusername, src ? &src->confrewriteusername : NULL) || !mergeconfstring(&dst->dynamiclookupcommand, src ? &src->dynamiclookupcommand : NULL) || !mergeconfstring(&dst->fticks_viscountry, src ? &src->fticks_viscountry : NULL) || !mergeconfstring(&dst->fticks_visinst, src ? &src->fticks_visinst : NULL) || !mergeconfstring(&dst->sniservername, src ? &src->sniservername : NULL) || !mergeconfstring(&dst->servername, src ? &src->servername : NULL)) return 0; if (src) { if (src->pdef) dst->pdef = src->pdef; dst->statusserver = src->statusserver; dst->certnamecheck = src->certnamecheck; if (src->retryinterval != 255) dst->retryinterval = src->retryinterval; if (src->retrycount != 255) dst->retrycount = src->retrycount; dst->blockingstartup = src->blockingstartup; dst->sni = src->sni; } dst->shallow = 0; return 1; } /** Set *AF according to IPV4ONLY and IPV6ONLY: - If both are set, the function fails. - If exactly one is set, *AF is set accordingly. - If none is set, *AF is not affected. Return 0 on success and !0 on failure. In the case of an error, *AF is not affected. */ int config_hostaf(const char *desc, int ipv4only, int ipv6only, int *af) { assert(af != NULL); if (ipv4only && ipv6only) { debug(DBG_ERR, "error in block %s, at most one of IPv4Only and " "IPv6Only can be enabled", desc); return -1; } if (ipv4only) *af = AF_INET; if (ipv6only) *af = AF_INET6; return 0; } static int confapplytls(struct clsrvconf *conf, const char *block, char *defaulttls) { #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) if (conf->type == RAD_TLS || conf->type == RAD_DTLS) { if (conf->tls) conf->tlsconf = tlsgettls(conf->tls); else { if (conf->pskkey) conf->tlsconf = tlsgetdefaultpsk(); else if (!(conf->tlsconf = tlsgettls(defaulttls))) conf->tlsconf = tlsgettls("default"); } if (!conf->tlsconf) { debug(DBG_ERR, "error in block %s, no tls context defined", block); return 0; } if (!conf->pskkey && !conf->tlsconf->certfile) { debug(DBG_ERR, "error in block %s, tls context %s has no certificate", block, conf->tlsconf->name); return 0; } if (conf->confmatchcertattrs) { int i; for (i = 0; conf->confmatchcertattrs[i]; i++) { if (!addmatchcertattr(conf, conf->confmatchcertattrs[i])) { debug(DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block); return 0; } } } if (!tlsgetctx(conf->type, conf->tlsconf)) { debug(DBG_ERR, "failed to initialize TLS context %s for block %s", conf->tlsconf->name, block); return 0; } } return 1; #else debug(DBG_ERR, "cannot apply tls config, radsecproxy was not compiled with TLS/DTLS support"); return 0; #endif return 1; } int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf, *existing; char *conftype = NULL, *rewriteinalias = NULL; long int dupinterval = LONG_MIN, addttl = LONG_MIN; uint8_t ipv4only = 0, ipv6only = 0; struct list_node *entry; debug(DBG_DBG, "confclient_cb called for %s", block); conf = calloc(1, sizeof(struct clsrvconf)); if (!conf) debugx(1, DBG_ERR, "malloc failed"); conf->certnamecheck = 1; if (!getgenericconfig( cf, block, "type", CONF_STR, &conftype, "host", CONF_MSTR, &conf->hostsrc, "IPv4Only", CONF_BLN, &ipv4only, "IPv6Only", CONF_BLN, &ipv6only, "secret", CONF_STR_NOESC, &conf->secret, #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) "tls", CONF_STR, &conf->tls, "PSKidentity", CONF_STR, &conf->pskid, "PSKkey", CONF_STR_NOESC, &conf->pskkey, "MatchCertificateAttribute", CONF_MSTR, &conf->confmatchcertattrs, "CertificateNameCheck", CONF_BLN, &conf->certnamecheck, "ServerName", CONF_STR, &conf->servername, #endif "DuplicateInterval", CONF_LINT, &dupinterval, "addTTL", CONF_LINT, &addttl, "tcpKeepalive", CONF_BLN, &conf->keepalive, "rewrite", CONF_STR, &rewriteinalias, "rewriteIn", CONF_STR, &conf->confrewritein, "rewriteOut", CONF_STR, &conf->confrewriteout, "rewriteattribute", CONF_STR, &conf->confrewriteusername, "fticksVISCOUNTRY", CONF_STR, &conf->fticks_viscountry, "fticksVISINST", CONF_STR, &conf->fticks_visinst, "requireMessageAuthenticator", CONF_BLN, &conf->reqmsgauth, "requireMessageAuthenticatorProxy", CONF_BLN, &conf->reqmsgauthproxy, NULL)) debugx(1, DBG_ERR, "configuration error"); conf->name = stringcopy(val, 0); if (conf->name && !conf->hostsrc) { conf->hostsrc = malloc(2 * sizeof(char *)); if (conf->hostsrc) { conf->hostsrc[0] = stringcopy(val, 0); conf->hostsrc[1] = NULL; } } if (!conf->name || !conf->hostsrc || !conf->hostsrc[0]) debugx(1, DBG_ERR, "malloc failed"); if (!conftype) debugx(1, DBG_ERR, "error in block %s, option type missing", block); conf->type = protoname2int(conftype); if (conf->type == 255) debugx(1, DBG_ERR, "error in block %s, unknown transport %s", block, conftype); free(conftype); conf->pdef = protodefs[conf->type]; if (!confapplytls(conf, block, "defaultClient")) debugx(1, DBG_ERR, "config error: ^"); conf->hostaf = AF_UNSPEC; if (config_hostaf("top level", options.ipv4only, options.ipv6only, &conf->hostaf)) debugx(1, DBG_ERR, "config error: ^"); if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf)) debugx(1, DBG_ERR, "error in block %s: ^", block); if (dupinterval != LONG_MIN) { if (dupinterval < 0 || dupinterval > 255) debugx(1, DBG_ERR, "error in block %s, value of option DuplicateInterval is %d, must be 0-255", block, dupinterval); conf->dupinterval = (uint8_t)dupinterval; } else conf->dupinterval = conf->pdef->duplicateintervaldefault; if (addttl != LONG_MIN) { if (addttl < 1 || addttl > 255) debugx(1, DBG_ERR, "error in block %s, value of option addTTL is %d, must be 1-255", block, addttl); conf->addttl = (uint8_t)addttl; } if (!conf->confrewritein) conf->confrewritein = rewriteinalias; else free(rewriteinalias); if (conf->confrewritein) { conf->rewritein = getrewrite(conf->confrewritein, NULL); if (!conf->rewritein) debugx(1, DBG_ERR, "error in block %s, rewrite block %s not defined", block, conf->confrewritein); } if (!conf->rewritein) conf->rewritein = getrewrite("defaultClient", "default"); if (conf->confrewriteout) { conf->rewriteout = getrewrite(conf->confrewriteout, NULL); if (!conf->rewriteout) debugx(1, DBG_ERR, "error in block %s, rewrite block %s not defined", block, conf->confrewriteout); } if (conf->confrewriteusername) { conf->rewriteusername = extractmodattr(conf->confrewriteusername); if (!conf->rewriteusername) debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block); } if (!addhostport(&conf->hostports, conf->hostsrc, conf->pdef->portdefault, 1) || !resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) debugx(1, DBG_ERR, "%s: resolve failed, exiting", __func__); if (!conf->secret) { if (!conf->pdef->secretdefault) debugx(1, DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name); if (!(conf->secret = (unsigned char *)stringcopy(conf->pdef->secretdefault, 0))) debugx(1, DBG_ERR, "malloc failed"); } conf->secret_len = unhex((char *)conf->secret, 1); if (conf->tlsconf) { for (entry = list_first(clconfs); entry; entry = list_next(entry)) { existing = (struct clsrvconf *)entry->data; if (existing->type == conf->type && existing->tlsconf != conf->tlsconf && hostportmatches(existing->hostports, conf->hostports, 0)) { debugx(1, DBG_ERR, "error in block %s, masked by overlapping (equal or less specific IP/prefix) client %s with different tls block", block, existing->name); } } } if (conf->pskkey) { conf->pskkeylen = unhex((char *)conf->pskkey, 1); if (conf->pskkeylen < PSK_MIN_LENGTH) debugx(1, DBG_ERR, "error in block %s, PSKkey must be at least %d bytes", block, PSK_MIN_LENGTH); if (!conf->pskid) { conf->pskid = stringcopy(conf->name, 0); debug(DBG_DBG, "confclientcb: using client name %s as PSKidentity", conf->name); } if (!verifyutf8((unsigned char *)conf->pskid, strlen(conf->pskid))) debugx(1, DBG_ERR, "error in block %s, PSKidentity must be a utf-8 string", block); if (strlen(conf->pskid) > PSK_ID_MAX_LENGTH) debugx(1, DBG_ERR, "error in block %s, PSKidentity must not be more than %d bytes", block, PSK_ID_MAX_LENGTH); } conf->lock = malloc(sizeof(pthread_mutex_t)); if (!conf->lock) debugx(1, DBG_ERR, "malloc failed"); pthread_mutex_init(conf->lock, NULL); if (!list_push(clconfs, conf)) debugx(1, DBG_ERR, "malloc failed"); return 1; } int compileserverconfig(struct clsrvconf *conf, const char *block) { /* in case conf is a (partially) shallow copy, clear some old pointer so we don't accidentially free them in case of errors */ conf->hostports = NULL; conf->matchcertattrs = NULL; if (!confapplytls(conf, block, "defaultServer")) return 0; if (!conf->portsrc) { conf->portsrc = stringcopy(conf->pdef->portdefault, 0); if (!conf->portsrc) { debug(DBG_ERR, "malloc failed"); return 0; } } if (conf->retryinterval == 255) conf->retryinterval = conf->pdef->retryintervaldefault; if (conf->retrycount == 255) conf->retrycount = conf->pdef->retrycountdefault; if (conf->confrewritein) { conf->rewritein = getrewrite(conf->confrewritein, NULL); if (!conf->rewritein) { debug(DBG_ERR, "error in block %s, rewrite block %s not defined", block, conf->rewritein); return 0; } } if (!conf->rewritein) conf->rewritein = getrewrite("defaultServer", "default"); if (conf->confrewriteout) { conf->rewriteout = getrewrite(conf->confrewriteout, NULL); if (!conf->rewriteout) { debug(DBG_ERR, "error in block %s, rewrite block %s not defined", block, conf->rewriteout); return 0; } } if (!addhostport(&conf->hostports, conf->hostsrc, conf->portsrc, 0)) { debug(DBG_ERR, "error in block %s, failed to parse %s", block, *conf->hostsrc); return 0; } if (!resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) { debug(DBG_ERR, "%s: resolve failed", __func__); return 0; } return 1; } int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf, *resconf; char *conftype = NULL, *rewriteinalias = NULL, *statusserver = NULL; long int retryinterval = LONG_MIN, retrycount = LONG_MIN, addttl = LONG_MIN; uint8_t ipv4only = 0, ipv6only = 0, confmerged = 0; debug(DBG_DBG, "confserver_cb called for %s", block); conf = calloc(1, sizeof(struct clsrvconf)); if (!conf) { debug(DBG_ERR, "malloc failed"); return 0; } conf->loopprevention = UCHAR_MAX; /* Uninitialized. */ resconf = (struct clsrvconf *)arg; if (resconf) { conf->statusserver = resconf->statusserver; conf->certnamecheck = resconf->certnamecheck; conf->secret_len = resconf->secret_len; conf->blockingstartup = resconf->blockingstartup; conf->type = resconf->type; conf->sni = resconf->sni; } else { conf->certnamecheck = 1; conf->sni = options.sni; } if (!getgenericconfig(cf, block, "type", CONF_STR, &conftype, "host", CONF_MSTR, &conf->hostsrc, "IPv4Only", CONF_BLN, &ipv4only, "IPv6Only", CONF_BLN, &ipv6only, "port", CONF_STR, &conf->portsrc, "source", CONF_MSTR, &conf->source, "secret", CONF_STR_NOESC, &conf->secret, #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) "tls", CONF_STR, &conf->tls, "PSKidentity", CONF_STR, &conf->pskid, "PSKkey", CONF_STR_NOESC, &conf->pskkey, "MatchCertificateAttribute", CONF_MSTR, &conf->confmatchcertattrs, "CertificateNameCheck", CONF_BLN, &conf->certnamecheck, "ServerName", CONF_STR, &conf->servername, #endif "addTTL", CONF_LINT, &addttl, "tcpKeepalive", CONF_BLN, &conf->keepalive, "rewrite", CONF_STR, &rewriteinalias, "rewriteIn", CONF_STR, &conf->confrewritein, "rewriteOut", CONF_STR, &conf->confrewriteout, "StatusServer", CONF_STR, &statusserver, "RetryInterval", CONF_LINT, &retryinterval, "RetryCount", CONF_LINT, &retrycount, "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand, "LoopPrevention", CONF_BLN, &conf->loopprevention, "BlockingStartup", CONF_BLN, &conf->blockingstartup, "SNI", CONF_BLN, &conf->sni, "SNIservername", CONF_STR, &conf->sniservername, "DTLSForceMTU", CONF_LINT, &conf->dtlsmtu, "requireMessageAuthenticator", CONF_BLN, &conf->reqmsgauth, NULL)) { debug(DBG_ERR, "configuration error"); goto errexit; } conf->name = stringcopy(val, 0); if (conf->name && !conf->hostsrc) { conf->hostsrc = malloc(2 * sizeof(char *)); if (conf->hostsrc) { conf->hostsrc[0] = stringcopy(val, 0); conf->hostsrc[1] = NULL; } } if (!conf->name || !conf->hostsrc || !conf->hostsrc[0]) { debug(DBG_ERR, "malloc failed"); goto errexit; } if (!conftype) { if (!resconf) { debug(DBG_ERR, "error in block %s, option type missing", block); goto errexit; } } else { conf->type = protoname2int(conftype); if (conf->type == 255) { debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype); goto errexit; } free(conftype); conftype = NULL; conf->pdef = protodefs[conf->type]; } conf->hostaf = AF_UNSPEC; if (config_hostaf("top level", options.ipv4only, options.ipv6only, &conf->hostaf) || config_hostaf(block, ipv4only, ipv6only, &conf->hostaf)) { debug(DBG_ERR, "config error: ^"); goto errexit; } if (!conf->confrewritein) conf->confrewritein = rewriteinalias; else free(rewriteinalias); rewriteinalias = NULL; if (retryinterval != LONG_MIN) { if (retryinterval < 1 || retryinterval > conf->pdef->retryintervalmax) { debug(DBG_ERR, "error in block %s, value of option RetryInterval is %ld, must be 1-%d", block, retryinterval, conf->pdef->retryintervalmax); goto errexit; } conf->retryinterval = (uint8_t)retryinterval; } else conf->retryinterval = 255; if (retrycount != LONG_MIN) { if (retrycount < 0 || retrycount > conf->pdef->retrycountmax) { debug(DBG_ERR, "error in block %s, value of option RetryCount is %ld, must be 0-%d", block, retrycount, conf->pdef->retrycountmax); goto errexit; } conf->retrycount = (uint8_t)retrycount; } else conf->retrycount = 255; if (addttl != LONG_MIN) { if (addttl < 1 || addttl > 255) { debug(DBG_ERR, "error in block %s, value of option addTTL is %ld, must be 1-255", block, addttl); goto errexit; } conf->addttl = (uint8_t)addttl; } if (statusserver) { if (strcasecmp(statusserver, "Off") == 0) conf->statusserver = RSP_STATSRV_OFF; else if (strcasecmp(statusserver, "On") == 0) conf->statusserver = RSP_STATSRV_ON; else if (strcasecmp(statusserver, "Minimal") == 0) conf->statusserver = RSP_STATSRV_MINIMAL; else if (strcasecmp(statusserver, "Auto") == 0) conf->statusserver = RSP_STATSRV_AUTO; else { debug(DBG_ERR, "config error in block %s: invalid StatusServer value: %s", block, statusserver); goto errexit; } free(statusserver); statusserver = NULL; } if (!conf->secret) { if (!resconf) { if (!conf->pdef->secretdefault) { debug(DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name); goto errexit; } if (!(conf->secret = (unsigned char *)stringcopy(conf->pdef->secretdefault, 0))) { debug(DBG_ERR, "malloc failed"); goto errexit; } } } if (conf->secret) conf->secret_len = unhex((char *)conf->secret, 1); if (conf->pskkey) { conf->pskkeylen = unhex((char *)conf->pskkey, 1); if (conf->pskkeylen < PSK_MIN_LENGTH) { debug(DBG_ERR, "error in block %s, PSKkey must be at least %d bytes", block, PSK_MIN_LENGTH); goto errexit; } if (!conf->pskid) { debug(DBG_ERR, "error in block %s, PSKidentity must be set to use PSK", block); goto errexit; } if (!verifyutf8((unsigned char *)conf->pskid, strlen(conf->pskid))) { debug(DBG_ERR, "error in block %s, PSKidentity must be a utf-8 string", block); goto errexit; } if (strlen(conf->pskid) > PSK_ID_MAX_LENGTH) { debug(DBG_ERR, "error in block %s, PSKidentity must not be more than %d bytes", block, PSK_ID_MAX_LENGTH); goto errexit; } } if (conf->sniservername) conf->sni = 1; if (resconf) { if (!mergesrvconf(resconf, conf)) goto errexit; free(conf); conf = resconf; confmerged = 1; } if (resconf || !conf->dynamiclookupcommand) { if (!compileserverconfig(conf, block)) goto errexit; } if (resconf) return 1; if (!list_push(srvconfs, conf)) { debug(DBG_ERR, "malloc failed"); goto errexit; } return 1; errexit: free(conftype); free(rewriteinalias); free(statusserver); /* if conf was merged into resconf, don't free it */ if (!confmerged) freeclsrvconf(conf); return 0; } int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { uint8_t whitelist_mode = 0; char **rmattrs = NULL, **rmvattrs = NULL; char **wlattrs = NULL, **wlvattrs = NULL; char **addattrs = NULL, **addvattrs = NULL; char **modattrs = NULL, **modvattrs = NULL; char **supattrs = NULL, **supvattrs = NULL; debug(DBG_DBG, "confrewrite_cb called for %s", block); if (!getgenericconfig(cf, block, "whitelistMode", CONF_BLN, &whitelist_mode, "removeAttribute", CONF_MSTR, &rmattrs, "removeVendorAttribute", CONF_MSTR, &rmvattrs, "whitelistAttribute", CONF_MSTR, &wlattrs, "whitelistVendorAttribute", CONF_MSTR, &wlvattrs, "addAttribute", CONF_MSTR_NOESC, &addattrs, "addVendorAttribute", CONF_MSTR_NOESC, &addvattrs, "modifyAttribute", CONF_MSTR, &modattrs, "modifyVendorAttribute", CONF_MSTR, &modvattrs, "supplementAttribute", CONF_MSTR_NOESC, &supattrs, "supplementVendorAttribute", CONF_MSTR_NOESC, &supvattrs, NULL)) debugx(1, DBG_ERR, "configuration error"); addrewrite(val, whitelist_mode, whitelist_mode ? wlattrs : rmattrs, whitelist_mode ? wlvattrs : rmvattrs, addattrs, addvattrs, modattrs, modvattrs, supattrs, supvattrs); freegconfmstr(whitelist_mode ? rmattrs : wlattrs); freegconfmstr(whitelist_mode ? rmvattrs : wlvattrs); return 1; } int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char **servers = NULL, **accservers = NULL, *msg = NULL; uint8_t accresp = 0, acclog = 0; debug(DBG_DBG, "confrealm_cb called for %s", block); if (!getgenericconfig(cf, block, "server", CONF_MSTR, &servers, "accountingServer", CONF_MSTR, &accservers, "ReplyMessage", CONF_STR, &msg, "AccountingResponse", CONF_BLN, &accresp, "AccountingLog", CONF_BLN, &acclog, NULL)) debugx(1, DBG_ERR, "configuration error"); if (!addrealm(realms, val, servers, accservers, msg, accresp, acclog)) { debug(DBG_ERR, "failed to add %s", block); return 0; } return 1; } int setprotoopts(uint8_t type, char **listenargs, char **sourcearg) { struct commonprotoopts *protoopts; protoopts = malloc(sizeof(struct commonprotoopts)); if (!protoopts) return 0; memset(protoopts, 0, sizeof(struct commonprotoopts)); protoopts->listenargs = listenargs; protoopts->sourcearg = sourcearg; protodefs[type]->setprotoopts(protoopts); return 1; } void warnpskreuse(struct list_node *entry, struct clsrvconf *conf, char *type, uint8_t warnidentity) { for (; entry; entry = list_next(entry)) { struct clsrvconf *existing = (struct clsrvconf *)entry->data; if (existing->pskkey && existing->pskkeylen == conf->secret_len && memcmp(existing->pskkey, conf->secret, conf->secret_len) == 0) debug(DBG_WARN, "WARNING: reuse of shared secrets as psk keys is NOT RECOMMENDED! (%s %s vs %s)", type, conf->name, existing->name); if (!conf->pskkey) continue; if (existing->secret_len == conf->pskkeylen && memcmp(existing->secret, conf->pskkey, conf->pskkeylen) == 0) debug(DBG_WARN, "WARNING: reuse of shared secrets as psk keys is NOT RECOMMENDED! (%s %s vs %s)", type, conf->name, existing->name); if (existing->pskkey && existing->pskkeylen == conf->pskkeylen && memcmp(existing->pskkey, conf->pskkey, conf->pskkeylen) == 0) debug(DBG_WARN, "WARNING: reuse of psk keys is NOT RECOMMENDED! (%s %s vs %s)", type, conf->name, existing->name); if (warnidentity && existing->pskid && strcmp(existing->pskid, conf->pskid) == 0) debug(DBG_WARN, "WARNING: reuse of psk identities is NOT RECOMMENDED! (%s %s vs %s)", type, conf->name, existing->name); } } void warnsecretlength(struct clsrvconf *conf, char *type) { if ((conf->type == RAD_UDP || conf->type == RAD_TCP) && conf->secret_len <= RSP_SECRET_LEN_WARN) debug(DBG_WARN, "warning! shared secret should be at least %d characters long! (block %s %s)", RSP_SECRET_LEN_WARN, type, conf->name); } void getmainconfig(const char *configfile) { long int addttl = LONG_MIN, loglevel = LONG_MIN; struct gconffile *cfs; char **listenargs[RAD_PROTOCOUNT]; char **sourceargs[RAD_PROTOCOUNT]; char *log_mac_str = NULL; char *log_key_str = NULL; uint8_t *fticks_reporting_str = NULL; uint8_t *fticks_mac_str = NULL; uint8_t *fticks_key_str = NULL; int i; cfs = openconfigfile(configfile); memset(&options, 0, sizeof(options)); memset(&listenargs, 0, sizeof(listenargs)); memset(&sourceargs, 0, sizeof(sourceargs)); options.logfullusername = 1; options.verifyeap = 1; clconfs = list_create(); if (!clconfs) debugx(1, DBG_ERR, "malloc failed"); srvconfs = list_create(); if (!srvconfs) debugx(1, DBG_ERR, "malloc failed"); realms = list_create(); if (!realms) debugx(1, DBG_ERR, "malloc failed"); if (!getgenericconfig( &cfs, NULL, #ifdef RADPROT_UDP "ListenUDP", CONF_MSTR, &listenargs[RAD_UDP], "SourceUDP", CONF_MSTR, &sourceargs[RAD_UDP], #endif #ifdef RADPROT_TCP "ListenTCP", CONF_MSTR, &listenargs[RAD_TCP], "SourceTCP", CONF_MSTR, &sourceargs[RAD_TCP], #endif #ifdef RADPROT_TLS "ListenTLS", CONF_MSTR, &listenargs[RAD_TLS], "SourceTLS", CONF_MSTR, &sourceargs[RAD_TLS], #endif #ifdef RADPROT_DTLS "ListenDTLS", CONF_MSTR, &listenargs[RAD_DTLS], "SourceDTLS", CONF_MSTR, &sourceargs[RAD_DTLS], #endif "PidFile", CONF_STR, &options.pidfile, "TTLAttribute", CONF_STR, &options.ttlattr, "addTTL", CONF_LINT, &addttl, "LogLevel", CONF_LINT, &loglevel, "LogDestination", CONF_STR, &options.logdestination, "LogThreadId", CONF_BLN, &options.logtid, "LogMAC", CONF_STR, &log_mac_str, "LogKey", CONF_STR, &log_key_str, "LogFullUsername", CONF_BLN, &options.logfullusername, "LoopPrevention", CONF_BLN, &options.loopprevention, "Client", CONF_CBK, confclient_cb, NULL, "Server", CONF_CBK, confserver_cb, NULL, "Realm", CONF_CBK, confrealm_cb, NULL, #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) "TLS", CONF_CBK, conftls_cb, NULL, #endif "Rewrite", CONF_CBK, confrewrite_cb, NULL, "FTicksReporting", CONF_STR, &fticks_reporting_str, "FTicksMAC", CONF_STR, &fticks_mac_str, "FTicksKey", CONF_STR, &fticks_key_str, "FTicksSyslogFacility", CONF_STR, &options.ftickssyslogfacility, "FTicksPrefix", CONF_STR, &options.fticksprefix, "IPv4Only", CONF_BLN, &options.ipv4only, "IPv6Only", CONF_BLN, &options.ipv6only, "SNI", CONF_BLN, &options.sni, "VerifyEAP", CONF_BLN, &options.verifyeap, NULL)) debugx(1, DBG_ERR, "configuration error"); if (loglevel != LONG_MIN) { if (loglevel < 1 || loglevel > 5) debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %d, must be 1, 2, 3, 4 or 5", configfile, loglevel); options.loglevel = (uint8_t)loglevel; } if (log_mac_str != NULL) { if (strcasecmp(log_mac_str, "Static") == 0) options.log_mac = RSP_MAC_STATIC; else if (strcasecmp(log_mac_str, "Original") == 0) options.log_mac = RSP_MAC_ORIGINAL; else if (strcasecmp(log_mac_str, "VendorHashed") == 0) options.log_mac = RSP_MAC_VENDOR_HASHED; else if (strcasecmp(log_mac_str, "VendorKeyHashed") == 0) options.log_mac = RSP_MAC_VENDOR_KEY_HASHED; else if (strcasecmp(log_mac_str, "FullyHashed") == 0) options.log_mac = RSP_MAC_FULLY_HASHED; else if (strcasecmp(log_mac_str, "FullyKeyHashed") == 0) options.log_mac = RSP_MAC_FULLY_KEY_HASHED; else { debugx(1, DBG_ERR, "config error: invalid LogMAC value: %s", log_mac_str); } if (log_key_str != NULL) { options.log_key = (uint8_t *)log_key_str; } else if ((options.log_mac == RSP_MAC_VENDOR_KEY_HASHED || options.log_mac == RSP_MAC_FULLY_KEY_HASHED)) { debugx(1, DBG_ERR, "config error: LogMAC %s requires LogKey to be set.", log_mac_str); } free(log_mac_str); } else { options.log_mac = RSP_MAC_ORIGINAL; } if (addttl != LONG_MIN) { if (addttl < 1 || addttl > 255) debugx(1, DBG_ERR, "error in %s, value of option addTTL is %d, must be 1-255", configfile, addttl); options.addttl = (uint8_t)addttl; } if (!setttlattr(&options, DEFAULT_TTL_ATTR)) debugx(1, DBG_ERR, "Failed to set TTLAttribute, exiting"); if (!options.fticksprefix) options.fticksprefix = DEFAULT_FTICKS_PREFIX; fticks_configure(&options, &fticks_reporting_str, &fticks_mac_str, &fticks_key_str); for (i = 0; i < RAD_PROTOCOUNT; i++) if (listenargs[i] || sourceargs[i]) setprotoopts(i, listenargs[i], sourceargs[i]); } void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile, char **pidfile) { int c; while ((c = getopt(argc, argv, "c:d:i:fpv")) != -1) { switch (c) { case 'c': *configfile = optarg; break; case 'd': if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '5') debugx(1, DBG_ERR, "Debug level must be 1, 2, 3, 4 or 5, not %s", optarg); *loglevel = *optarg - '0'; break; case 'f': *foreground = 1; break; case 'i': *pidfile = optarg; break; case 'p': *pretend = 1; break; case 'v': debug(DBG_ERR, "radsecproxy revision %s", PACKAGE_VERSION); #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) debug(DBG_ERR, "using %s", SSLeay_version(SSLEAY_VERSION)); #endif debug(DBG_ERR, "This binary was built with support for the following transports:"); #ifdef RADPROT_UDP debug(DBG_ERR, " UDP"); #endif #ifdef RADPROT_TCP debug(DBG_ERR, " TCP"); #endif #ifdef RADPROT_TLS debug(DBG_ERR, " TLS"); #endif #ifdef RADPROT_DTLS debug(DBG_ERR, " DTLS"); #endif exit(0); default: goto usage; } } if (!(argc - optind)) return; usage: debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -i pidfile ] [ -p ] [ -v ]", argv[0]); } #ifdef SYS_SOLARIS int daemon(int a, int b) { int i; if (fork()) exit(0); setsid(); for (i = 0; i < 3; i++) { close(i); open("/dev/null", O_RDWR); } return 1; } #endif void revalidateconnections(void) { struct list_node *entry, *client_entry, *subrealm_entry, *conf_entry; struct clsrvconf *conf; debug(DBG_DBG, "revalidateconnections: revalidating clients"); for (entry = list_first(clconfs); entry; entry = list_next(entry)) { struct clsrvconf *clconf = (struct clsrvconf *)entry->data; if (!(clconf->type == RAD_TLS || clconf->type == RAD_DTLS)) continue; pthread_mutex_lock(clconf->lock); for (client_entry = list_first(clconf->clients); client_entry; client_entry = list_next(client_entry)) terminateinvalidclient((struct client *)client_entry->data); pthread_mutex_unlock(clconf->lock); } debug(DBG_DBG, "revalidateconnections: revalidating servers"); for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { struct clsrvconf *srvconf = (struct clsrvconf *)entry->data; if (!(srvconf->type == RAD_TLS || srvconf->type == RAD_DTLS)) continue; terminateinvalidserver(srvconf->servers); } debug(DBG_DBG, "revalidateconnections: revalidating dynamic servers"); for (entry = list_first(realms); entry; entry = list_next(entry)) { struct realm *realm = (struct realm *)entry->data; pthread_mutex_lock(&realm->mutex); for (subrealm_entry = list_first(realm->subrealms); subrealm_entry; subrealm_entry = list_next(subrealm_entry)) { struct realm *subrealm = (struct realm *)subrealm_entry->data; pthread_mutex_lock(&subrealm->mutex); for (conf_entry = list_first(subrealm->srvconfs); conf_entry; conf_entry = list_next(conf_entry)) { conf = (struct clsrvconf *)conf_entry->data; if (!(conf->type == RAD_TLS || conf->type == RAD_DTLS)) continue; if (conf->servers && conf->servers->dynamiclookuparg) terminateinvalidserver(conf->servers); } for (conf_entry = list_first(subrealm->accsrvconfs); conf_entry; conf_entry = list_next(conf_entry)) { conf = (struct clsrvconf *)conf_entry->data; if (!(conf->type == RAD_TLS || conf->type == RAD_DTLS)) continue; if (conf->servers && conf->servers->dynamiclookuparg) terminateinvalidserver(conf->servers); } pthread_mutex_unlock(&subrealm->mutex); } pthread_mutex_unlock(&realm->mutex); } } void *sighandler(void *arg) { sigset_t sigset; int sig; for (;;) { sigemptyset(&sigset); sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGPIPE); sigwait(&sigset, &sig); switch (sig) { case 0: /* completely ignoring this */ break; case SIGHUP: debug(DBG_INFO, "sighandler: got SIGHUP"); debug_reopen_log(); #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) tlsreload(); revalidateconnections(); #endif break; case SIGPIPE: debug(DBG_WARN, "sighandler: got SIGPIPE, TLS write error?"); break; default: debug(DBG_WARN, "sighandler: ignoring signal %d", sig); } } } int createpidfile(const char *pidfile) { int r = 0; FILE *f = fopen(pidfile, "w"); if (f) r = fprintf(f, "%ld\n", (long)getpid()); return f && !fclose(f) && r >= 0; } int radsecproxy_main(int argc, char **argv) { pthread_t sigth; sigset_t sigset; size_t stacksize; struct list_node *entry; uint8_t foreground = 0, pretend = 0, loglevel = 0; char *configfile = NULL, *pidfile = NULL; struct clsrvconf *srvconf; int i; debug_init("radsecproxy"); debug_set_level(DEBUG_LEVEL); if (pthread_attr_init(&pthread_attr)) debugx(1, DBG_ERR, "pthread_attr_init failed"); #if defined(PTHREAD_STACK_MIN) stacksize = THREAD_STACK_SIZE > PTHREAD_STACK_MIN ? THREAD_STACK_SIZE : PTHREAD_STACK_MIN; #else stacksize = THREAD_STACK_SIZE; #endif if (pthread_attr_setstacksize(&pthread_attr, stacksize)) debug(DBG_WARN, "pthread_attr_setstacksize failed! Using system default. Memory footprint might be increased!"); #if defined(HAVE_MALLOPT) if (mallopt(M_TRIM_THRESHOLD, 4 * 1024) != 1) debugx(1, DBG_ERR, "mallopt failed"); #endif for (i = 0; i < RAD_PROTOCOUNT; i++) protodefs[i] = protoinits[i](i); /* needed even if no TLS/DTLS transport */ randinit(); #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) sslinit(); #endif getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile, &pidfile); if (loglevel) debug_set_level(loglevel); getmainconfig(configfile ? configfile : CONFIG_MAIN); if (loglevel) options.loglevel = loglevel; else if (options.loglevel) debug_set_level(options.loglevel); if (!foreground) { debug_set_destination(options.logdestination ? options.logdestination : "x-syslog:///", LOG_TYPE_DEBUG); if (options.ftickssyslogfacility) { debug_set_destination(options.ftickssyslogfacility, LOG_TYPE_FTICKS); free(options.ftickssyslogfacility); } } free(options.logdestination); if (options.logtid) debug_tid_on(); if (!pretend) debug_reopen_log(); if (!list_first(clconfs)) debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting"); if (!list_first(realms)) debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting"); for (entry = list_first(clconfs); entry; entry = list_next(entry)) { warnpskreuse(list_next(entry), (struct clsrvconf *)entry->data, "client", 1); warnsecretlength((struct clsrvconf *)entry->data, "client"); } for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { warnpskreuse(list_next(entry), (struct clsrvconf *)entry->data, "server", 0); warnsecretlength((struct clsrvconf *)entry->data, "server"); } if (pretend) debugx(0, DBG_ERR, "All OK so far; exiting since only pretending"); if (!foreground && (daemon(0, 0) < 0)) debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno)); debug_timestamp_on(); debug(DBG_ERR, "radsecproxy %s starting", PACKAGE_VERSION); if (!pidfile) pidfile = options.pidfile; if (pidfile && !createpidfile(pidfile)) debugx(1, DBG_ERR, "failed to create pidfile %s: %s", pidfile, strerror(errno)); sigemptyset(&sigset); /* exit on all but SIGHUP|SIGPIPE, ignore more? */ sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGPIPE); pthread_sigmask(SIG_BLOCK, &sigset, NULL); if (pthread_create(&sigth, &pthread_attr, sighandler, NULL)) debugx(1, DBG_ERR, "pthread_create failed: sighandler"); for (entry = list_first(srvconfs); entry; entry = list_next(entry)) { srvconf = (struct clsrvconf *)entry->data; if (srvconf->dynamiclookupcommand) continue; if (!addserver(srvconf, NULL)) debugx(1, DBG_ERR, "failed to add server"); } for (i = 0; i < RAD_PROTOCOUNT; i++) { if (!protodefs[i]) continue; if (protodefs[i]->initextra) protodefs[i]->initextra(); if (find_clconf_type(i, NULL)) createlisteners(i); } /* just hang around doing nothing, anything to do here? */ for (;;) sleep(1000); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/rewrite.c0000644000076600000240000004412514722543325011460 /* Copyright (c) 2019, SWITCH */ /* See LICENSE for licensing information. */ #include "rewrite.h" #include "debug.h" #include "gconfig.h" #include "hash.h" #include "list.h" #include "radmsg.h" #include "util.h" #include #include #include #include #include static struct hash *rewriteconfs; /** Extract attributes from string NAMEVAL, create a struct tlv and * return the tlv. If VENDOR_FLAG, NAMEVAL is on the form * "::" and otherwise it's ":". Return * NULL if fields are missing or if conversion fails. * * FIXME: Should accept both names and numeric values, only numeric * right now */ struct tlv *extractattr(char *nameval, char vendor_flag) { int len, name = 0; int vendor = 0; /* Vendor 0 is reserved, see RFC 1700. */ uint32_t ival = 0; char *s, *s2; struct tlv *a; s = strchr(nameval, ':'); if (!s) return NULL; name = atoi(nameval); if (vendor_flag) { s2 = strchr(s + 1, ':'); if (!s2) return NULL; vendor = name; name = atoi(s + 1); s = s2; } s++; if (isdigit((int)*s)) { ival = atoi(s); ival = htonl(ival); len = 4; s = (char *)&ival; } else { if (*s == '\'') s++; len = unhex(s, 1); if (len > 253) return NULL; } if (name < 1 || name > 255) return NULL; a = malloc(sizeof(struct tlv)); if (!a) return NULL; a->v = (uint8_t *)stringcopy(s, len); if (!a->v) { free(a); return NULL; } a->t = name; a->l = len; if (vendor_flag) a = makevendortlv(vendor, a); return a; } /* should accept both names and numeric values, only numeric right now */ struct modattr *extractmodattr(char *nameval) { int name = 0; char *s, *t; struct modattr *m; if (!strncasecmp(nameval, "User-Name:/", 11)) { s = nameval + 11; name = 1; } else { s = strchr(nameval, ':'); name = atoi(nameval); if (!s || name < 1 || name > 255 || s[1] != '/') return NULL; s += 2; } /* regexp, remove optional trailing / if present */ if (s[strlen(s) - 1] == '/') s[strlen(s) - 1] = '\0'; for (t = strchr(s, '/'); t; t = strchr(t + 1, '/')) if (t == s || t[-1] != '\\') break; if (!t) return NULL; *t = '\0'; t++; m = malloc(sizeof(struct modattr)); if (!m) { debug(DBG_ERR, "malloc failed"); return NULL; } m->t = name; m->replacement = stringcopy(t, 0); if (!m->replacement) { free(m); debug(DBG_ERR, "malloc failed"); return NULL; } m->regex = malloc(sizeof(regex_t)); if (!m->regex) { free(m->replacement); free(m); debug(DBG_ERR, "malloc failed"); return NULL; } if (regcomp(m->regex, s, REG_ICASE | REG_EXTENDED)) { free(m->regex); free(m->replacement); free(m); debug(DBG_ERR, "failed to compile regular expression %s", s); return NULL; } return m; } struct modattr *extractmodvattr(char *nameval) { uint32_t vendor; char *s; struct modattr *modvattr; s = strchr(nameval, ':'); vendor = atoi(nameval); if (!s || !vendor || !strchr(s + 1, ':')) return NULL; modvattr = extractmodattr(s + 1); if (modvattr) modvattr->vendor = vendor; return modvattr; } void addrewrite(char *value, uint8_t whitelist_mode, char **rmattrs, char **rmvattrs, char **addattrs, char **addvattrs, char **modattrs, char **modvattrs, char **supattrs, char **supvattrs) { struct rewrite *rewrite = NULL; int i, n; uint8_t *rma = NULL; uint32_t *p, *rmva = NULL; struct list *adda = NULL, *moda = NULL, *modva = NULL, *supa = NULL; struct tlv *a; struct modattr *m; if (rmattrs) { for (n = 0; rmattrs[n];) n++; rma = calloc(n + 1, sizeof(uint8_t)); if (!rma) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; i < n; i++) if (!(rma[i] = attrname2val(rmattrs[i]))) debugx(1, DBG_ERR, "addrewrite: removing invalid attribute %s", rmattrs[i]); freegconfmstr(rmattrs); rma[i] = 0; } if (rmvattrs) { for (n = 0; rmvattrs[n];) n++; rmva = calloc(2 * n + 1, sizeof(uint32_t)); if (!rmva) debugx(1, DBG_ERR, "malloc failed"); for (p = rmva, i = 0; i < n; i++, p += 2) if (!vattrname2val(rmvattrs[i], p, p + 1)) debugx(1, DBG_ERR, "addrewrite: removing invalid vendor attribute %s", rmvattrs[i]); freegconfmstr(rmvattrs); *p = 0; } if (addattrs) { adda = list_create(); if (!adda) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; addattrs[i]; i++) { a = extractattr(addattrs[i], 0); if (!a) debugx(1, DBG_ERR, "addrewrite: adding invalid attribute %s", addattrs[i]); if (!list_push(adda, a)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(addattrs); } if (addvattrs) { if (!adda) adda = list_create(); if (!adda) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; addvattrs[i]; i++) { a = extractattr(addvattrs[i], 1); if (!a) debugx(1, DBG_ERR, "addrewrite: adding invalid vendor attribute %s", addvattrs[i]); if (!list_push(adda, a)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(addvattrs); } if (modattrs) { moda = list_create(); if (!moda) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; modattrs[i]; i++) { m = extractmodattr(modattrs[i]); if (!m) debugx(1, DBG_ERR, "addrewrite: modifying invalid attribute %s", modattrs[i]); if (!list_push(moda, m)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(modattrs); } if (modvattrs) { modva = list_create(); if (!modva) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; modvattrs[i]; i++) { m = extractmodvattr(modvattrs[i]); if (!m) debugx(1, DBG_ERR, "addrewrite: modifying invalid vendor attribute %s", modvattrs[i]); if (!list_push(modva, m)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(modvattrs); } if (supattrs) { supa = list_create(); if (!supa) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; supattrs[i]; i++) { a = extractattr(supattrs[i], 0); if (!a) debugx(1, DBG_ERR, "addrewrite: adding invalid attribute %s", supattrs[i]); if (!list_push(supa, a)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(supattrs); } if (supvattrs) { if (!supa) supa = list_create(); if (!supa) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; supvattrs[i]; i++) { a = extractattr(supvattrs[i], 1); if (!a) debugx(1, DBG_ERR, "addrewrite: adding invalid vendor attribute %s", supvattrs[i]); if (!list_push(supa, a)) debugx(1, DBG_ERR, "malloc failed"); } freegconfmstr(supvattrs); } if (rma || rmva || adda || moda || modva || supa) { rewrite = malloc(sizeof(struct rewrite)); if (!rewrite) debugx(1, DBG_ERR, "malloc failed"); rewrite->whitelist_mode = whitelist_mode; rewrite->removeattrs = rma; rewrite->removevendorattrs = rmva; rewrite->addattrs = adda; rewrite->modattrs = moda; rewrite->modvattrs = modva; rewrite->supattrs = supa; } if (!rewriteconfs) rewriteconfs = hash_create(); if (!hash_insert(rewriteconfs, value, strlen(value), rewrite)) debugx(1, DBG_ERR, "malloc failed"); debug(DBG_DBG, "addrewrite: added rewrite block %s", value); } struct rewrite *getrewrite(char *alt1, char *alt2) { struct rewrite *r; if (alt1) if ((r = hash_read(rewriteconfs, alt1, strlen(alt1)))) return r; if (alt2) if ((r = hash_read(rewriteconfs, alt2, strlen(alt2)))) return r; return NULL; } int findvendorsubattr(uint32_t *attrs, uint32_t vendor, uint32_t subattr) { if (!attrs) return 0; for (; attrs[0]; attrs += 2) if (attrs[0] == vendor && attrs[1] == subattr) return 1; return 0; } /* returns 1 if entire element is to be removed, else 0 */ int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs, int inverted) { uint8_t alen, sublen; uint32_t vendor; uint8_t *subattrs; if (!removevendorattrs || attr->l <= 4) return 0; memcpy(&vendor, attr->v, 4); vendor = ntohl(vendor); while (*removevendorattrs && *removevendorattrs != vendor) removevendorattrs += 2; if (!*removevendorattrs) return 0; if (findvendorsubattr(removevendorattrs, vendor, 256)) return 1; /* remove entire vendor attribute */ sublen = attr->l - 4; subattrs = attr->v + 4; if (!attrvalidate(subattrs, sublen)) { debug(DBG_INFO, "dovendorrewrite: vendor attribute validation failed, no rewrite"); return 0; } while (sublen > 1) { alen = ATTRLEN(subattrs); sublen -= alen; if (!!findvendorsubattr(removevendorattrs, vendor, ATTRTYPE(subattrs)) != !!inverted) { memmove(subattrs, subattrs + alen, sublen); attr->l -= alen; } else subattrs += alen; } if ((attr->l <= 4) != !!inverted) return 1; return 0; } /*if inverted is true, remove all attributes except those listed */ void dorewriterm(struct radmsg *msg, uint8_t *rmattrs, uint32_t *rmvattrs, int inverted) { struct list_node *n, *p; struct tlv *attr; p = NULL; n = list_first(msg->attrs); while (n) { attr = (struct tlv *)n->data; if (((rmattrs && strchr((char *)rmattrs, attr->t)) || (rmvattrs && attr->t == RAD_Attr_Vendor_Specific && dovendorrewriterm(attr, rmvattrs, inverted))) != !!inverted) { list_removedata(msg->attrs, attr); freetlv(attr); n = p ? list_next(p) : list_first(msg->attrs); } else { p = n; n = list_next(n); } } } int dorewritemodattr(struct tlv *attr, struct modattr *modattr) { size_t nmatch = 10, reslen = 0, start = 0; regmatch_t pmatch[10], *pfield; int i; char *in, *out; in = stringcopy((char *)attr->v, attr->l); if (!in) return 0; if (regexec(modattr->regex, in, nmatch, pmatch, 0)) { free(in); return 1; } out = modattr->replacement; for (i = start; out[i]; i++) { if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') { pfield = &pmatch[out[i + 1] - '0']; if (pfield->rm_so >= 0) { reslen += i - start + pfield->rm_eo - pfield->rm_so; start = i + 2; } i++; } } reslen += i - start; if (!resizeattr(attr, reslen)) { debug(DBG_INFO, "rewritten attribute to length %zu failed, discarding message", reslen); free(in); return 0; } start = 0; reslen = 0; for (i = start; out[i]; i++) { if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') { pfield = &pmatch[out[i + 1] - '0']; if (pfield->rm_so >= 0) { memcpy(attr->v + reslen, out + start, i - start); reslen += i - start; memcpy(attr->v + reslen, in + pfield->rm_so, pfield->rm_eo - pfield->rm_so); reslen += pfield->rm_eo - pfield->rm_so; start = i + 2; } i++; } } free(in); memcpy(attr->v + reslen, out + start, i - start); return 1; } int replacesubtlv(struct tlv *vendortlv, uint8_t *p, struct tlv *newtlv) { int size_diff; uint8_t rem_size, *next_attr; size_diff = newtlv->l - ATTRLEN(p); next_attr = p + ATTRLEN(p); rem_size = (vendortlv->v + vendortlv->l) - next_attr; if (size_diff < 0) memmove(next_attr + size_diff, next_attr, rem_size); if (!resizeattr(vendortlv, vendortlv->l + size_diff)) return 0; if (size_diff > 0) memmove(next_attr + size_diff, next_attr, rem_size); tlv2buf(p, newtlv); return 1; } int dorewritemodvattr(struct tlv *vendortlv, struct modattr *modvattr) { struct tlv *tmpattr; int offset; if (vendortlv->l <= 4 || !attrvalidate(vendortlv->v + 4, vendortlv->l - 4)) return 0; for (offset = 4; offset < vendortlv->l; offset += ATTRLEN(vendortlv->v + offset)) { if (ATTRTYPE(vendortlv->v + offset) == modvattr->t) { tmpattr = maketlv(ATTRTYPE(vendortlv->v + offset), ATTRVALLEN(vendortlv->v + offset), ATTRVAL(vendortlv->v + offset)); if (!tmpattr) return 0; if (dorewritemodattr(tmpattr, modvattr)) { int size_diff = tmpattr->l - ATTRVALLEN(vendortlv->v + offset); int rem_size = vendortlv->l - offset - ATTRLEN(vendortlv->v + offset); uint8_t *next; if (size_diff > 0) if (!resizeattr(vendortlv, vendortlv->l + size_diff)) { freetlv(tmpattr); return 0; } next = vendortlv->v + offset + ATTRLEN(vendortlv->v + offset); memmove(next + size_diff, next, rem_size); if (size_diff < 0) if (!resizeattr(vendortlv, vendortlv->l + size_diff)) { freetlv(tmpattr); return 0; } tlv2buf(vendortlv->v + offset, tmpattr); } else { freetlv(tmpattr); return 0; } freetlv(tmpattr); } } return 1; } int dorewritemod(struct radmsg *msg, struct list *modattrs, struct list *modvattrs) { struct list_node *n, *m; uint32_t vendor; for (n = list_first(msg->attrs); n; n = list_next(n)) { struct tlv *attr = (struct tlv *)n->data; if (attr->t == RAD_Attr_Vendor_Specific) { memcpy(&vendor, attr->v, 4); vendor = ntohl(vendor); for (m = list_first(modvattrs); m; m = list_next(m)) { if (vendor == ((struct modattr *)m->data)->vendor && !dorewritemodvattr(attr, (struct modattr *)m->data)) return 0; } } else { for (m = list_first(modattrs); m; m = list_next(m)) if (((struct tlv *)n->data)->t == ((struct modattr *)m->data)->t && !dorewritemodattr((struct tlv *)n->data, (struct modattr *)m->data)) return 0; } } return 1; } int dorewriteadd(struct radmsg *msg, struct list *addattrs) { struct list_node *n; struct tlv *a; for (n = list_first(addattrs); n; n = list_next(n)) { a = copytlv((struct tlv *)n->data); if (!a) return 0; if (!radmsg_add(msg, a, 0)) { freetlv(a); return 0; } } return 1; } int dorewritesupattr(struct radmsg *msg, struct tlv *supattr) { struct list_node *p; struct tlv *attr; uint8_t exist = 0, *vendortype, *v; for (p = list_first(msg->attrs); p; p = list_next(p)) { attr = (struct tlv *)p->data; if (attr->t == supattr->t && attr->t != RAD_Attr_Vendor_Specific) { exist = 1; break; } else if (supattr->t == RAD_Attr_Vendor_Specific && attr->t == RAD_Attr_Vendor_Specific && memcmp(supattr->v, attr->v, 4) == 0) { if (!attrvalidate(attr->v + 4, attr->l - 4)) { debug(DBG_INFO, "dorewritesup: vendor attribute validation failed, no rewrite"); return 0; } vendortype = (uint8_t *)supattr->v + 4; for (v = attr->v + 4; v < attr->v + attr->l; v += *(v + 1)) { if (*v == *vendortype) { exist = 1; break; } } if (exist) break; } } if (!exist) { supattr = copytlv(supattr); if (!supattr) return 0; if (!radmsg_add(msg, supattr, 0)) { freetlv(supattr); return 0; } } return 1; } int dorewritesup(struct radmsg *msg, struct list *supattrs) { struct list_node *n; for (n = list_first(supattrs); n; n = list_next(n)) { if (!dorewritesupattr(msg, (struct tlv *)n->data)) return 0; } return 1; } int dorewrite(struct radmsg *msg, struct rewrite *rewrite) { int rv = 1; /* Success. */ if (rewrite) { if (rewrite->removeattrs || rewrite->removevendorattrs) dorewriterm(msg, rewrite->removeattrs, rewrite->removevendorattrs, rewrite->whitelist_mode); if (rewrite->modattrs || rewrite->modvattrs) if (!dorewritemod(msg, rewrite->modattrs, rewrite->modvattrs)) rv = 0; if (rewrite->supattrs) if (!dorewritesup(msg, rewrite->supattrs)) rv = 0; if (rewrite->addattrs) if (!dorewriteadd(msg, rewrite->addattrs)) rv = 0; } return rv; } /** Ad vendor attribute with VENDOR + ATTR and push it on MSG. ATTR * is consumed. */ int addvendorattr(struct radmsg *msg, uint32_t vendor, struct tlv *attr) { struct tlv *vattr; vattr = makevendortlv(vendor, attr); if (!vattr) { freetlv(attr); return 0; } if (!radmsg_add(msg, vattr, 0)) { freetlv(vattr); return 0; } return 1; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/fticks_hashmac.h0000644000076600000240000000052414722543325012746 /* Copyright (c) 2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include #include int fticks_hashmac(const uint8_t *in, const uint8_t *key, size_t out_len, uint8_t *out); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/ax_check_openssl.m40000644000076600000240000001014514452772710013402 # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) AC_DEFUN([AX_CHECK_OPENSSL], [ found=false AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl=DIR], [root of the OpenSSL directory])], [ case "$withval" in "" | y | ye | yes | n | no) AC_MSG_ERROR([Invalid --with-openssl value]) ;; *) ssldirs="$withval" ;; esac ], [ # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs AC_CHECK_TOOL([PKG_CONFIG], [pkg-config]) if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi ] ) # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do AC_MSG_CHECKING([for include/openssl/ssl.h in $ssldir]) if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true AC_MSG_RESULT([yes]) break else AC_MSG_RESULT([no]) fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], [ AC_MSG_RESULT([yes]) $1 ], [ AC_MSG_RESULT([no]) $2 ]) CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" AC_SUBST([OPENSSL_INCLUDES]) AC_SUBST([OPENSSL_LIBS]) AC_SUBST([OPENSSL_LDFLAGS]) ]) radsecproxy-1.11.1/list.c0000644000076600000240000000706214722543325010751 /* Copyright (c) 2007-2009, UNINETT AS */ /* See LICENSE for licensing information. */ #include "list.h" #include #include /* Private helper functions. */ static void list_free_helper_(struct list *list, int free_data_flag) { struct list_node *node, *next; if (!list) return; for (node = list->first; node; node = next) { if (free_data_flag) free(node->data); next = node->next; free(node); } free(list); } /* Public functions. */ /* allocates and initialises list structure; returns NULL if malloc fails */ struct list *list_create(void) { struct list *list = malloc(sizeof(struct list)); if (list) memset(list, 0, sizeof(struct list)); return list; } /* frees all memory associated with the list note that the data pointed at from each node is also freed use list_free() to free only the memory used by the list itself */ void list_destroy(struct list *list) { list_free_helper_(list, 1); } /* frees the meory used by the list itself note that the data pointed at from each node is not freed use list_destroy() to free all the data associated with the list */ void list_free(struct list *list) { list_free_helper_(list, 0); } /* appends entry to list; returns 1 if ok, 0 if malloc fails */ int list_push(struct list *list, void *data) { struct list_node *node; node = malloc(sizeof(struct list_node)); if (!node) return 0; node->next = NULL; node->data = data; if (list->first) list->last->next = node; else list->first = node; list->last = node; list->count++; return 1; } /* insert entry at front of the list; returns 1 if ok, 0 if malloc fails */ int list_push_front(struct list *list, void *data) { struct list_node *node; node = malloc(sizeof(struct list_node)); if (!node) return 0; node->data = data; node->next = list->first; if (!list->first) list->last = node; list->first = node; list->count++; return 1; } /* removes first entry from list and returns data */ void *list_shift(struct list *list) { struct list_node *node; void *data; if (!list || !list->first) return NULL; node = list->first; list->first = node->next; if (!list->first) list->last = NULL; data = node->data; free(node); list->count--; return data; } /* removes all entries with matching data pointer */ void list_removedata(struct list *list, void *data) { struct list_node *node, *t; if (!list || !list->first) return; node = list->first; while (node->data == data) { list->first = node->next; free(node); list->count--; node = list->first; if (!node) { list->last = NULL; return; } } for (; node->next; node = node->next) if (node->next->data == data) { t = node->next; node->next = t->next; free(t); list->count--; if (!node->next) { /* we removed the last one */ list->last = node; return; } } } /* returns first node */ struct list_node *list_first(struct list *list) { return list ? list->first : NULL; } /* returns the next node after the argument */ struct list_node *list_next(struct list_node *node) { return node->next; } /* returns number of nodes */ uint32_t list_count(struct list *list) { return list->count; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/build-aux/0000755000076600000240000000000014724611072011574 5radsecproxy-1.11.1/build-aux/install-sh0000744000076600000240000003610114715040755013523 #!/bin/sh # install - install a program, script, or datafile scriptversion=2023-11-23.18; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Report bugs to . GNU Automake home page: . General help using GNU software: ." while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/build-aux/config.guess0000555000076600000240000014313414715040755014044 #!/nix/store/rj7zvmif800bgg3sbznq6g5g438jx104-bash-5.2p37/bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system '$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still # use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #if defined(__ANDROID__) LIBC=android #else #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #elif defined(__LLVM_LIBC__) LIBC=llvm #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case $UNAME_VERSION in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like '4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-pc-managarm-mlibc" ;; *:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __ARM_EABI__ #ifdef __ARM_PCS_VFP ABI=eabihf #else ABI=eabi #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;; esac fi GUESS=$CPU-unknown-linux-$LIBCABI ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; kvx:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; kvx:cos:*:*) GUESS=$UNAME_MACHINE-unknown-cos ;; kvx:mbr:*:*) GUESS=$UNAME_MACHINE-unknown-mbr ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __i386__ ABI=x86 #else #ifdef __ILP32__ ABI=x32 #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in x86) CPU=i686 ;; x32) LIBCABI=${LIBC}x32 ;; esac fi GUESS=$CPU-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; ppc:Haiku:*:*) # Haiku running on Apple PowerPC GUESS=powerpc-apple-haiku ;; *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "${cputype-}" = 386; then UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; *:Ironclad:*:*) GUESS=$UNAME_MACHINE-unknown-ironclad ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: radsecproxy-1.11.1/build-aux/depcomp0000555000076600000240000005602014715040755013076 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/build-aux/missing0000555000076600000240000001533614715040755013125 #! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2021 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/build-aux/tap-driver.sh0000555000076600000240000004600514715040755014137 #! /bin/sh # Copyright (C) 2011-2021 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . scriptversion=2013-12-23.17; # UTC # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u me=tap-driver.sh fatal () { echo "$me: fatal: $*" >&2 exit 1 } usage_error () { echo "$me: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat < # trap : 1 3 2 13 15 if test $merge -gt 0; then exec 2>&1 else exec 2>&3 fi "$@" echo $? ) | LC_ALL=C ${AM_TAP_AWK-awk} \ -v me="$me" \ -v test_script_name="$test_name" \ -v log_file="$log_file" \ -v trs_file="$trs_file" \ -v expect_failure="$expect_failure" \ -v merge="$merge" \ -v ignore_exit="$ignore_exit" \ -v comments="$comments" \ -v diag_string="$diag_string" \ ' # TODO: the usages of "cat >&3" below could be optimized when using # GNU awk, and/on on systems that supports /dev/fd/. # Implementation note: in what follows, `result_obj` will be an # associative array that (partly) simulates a TAP result object # from the `TAP::Parser` perl module. ## ----------- ## ## FUNCTIONS ## ## ----------- ## function fatal(msg) { print me ": " msg | "cat >&2" exit 1 } function abort(where) { fatal("internal error " where) } # Convert a boolean to a "yes"/"no" string. function yn(bool) { return bool ? "yes" : "no"; } function add_test_result(result) { if (!test_results_index) test_results_index = 0 test_results_list[test_results_index] = result test_results_index += 1 test_results_seen[result] = 1; } # Whether the test script should be re-run by "make recheck". function must_recheck() { for (k in test_results_seen) if (k != "XFAIL" && k != "PASS" && k != "SKIP") return 1 return 0 } # Whether the content of the log file associated to this test should # be copied into the "global" test-suite.log. function copy_in_global_log() { for (k in test_results_seen) if (k != "PASS") return 1 return 0 } function get_global_test_result() { if ("ERROR" in test_results_seen) return "ERROR" if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) return "FAIL" all_skipped = 1 for (k in test_results_seen) if (k != "SKIP") all_skipped = 0 if (all_skipped) return "SKIP" return "PASS"; } function stringify_result_obj(result_obj) { if (result_obj["is_unplanned"] || result_obj["number"] != testno) return "ERROR" if (plan_seen == LATE_PLAN) return "ERROR" if (result_obj["directive"] == "TODO") return result_obj["is_ok"] ? "XPASS" : "XFAIL" if (result_obj["directive"] == "SKIP") return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; if (length(result_obj["directive"])) abort("in function stringify_result_obj()") return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL } function decorate_result(result) { color_name = color_for_result[result] if (color_name) return color_map[color_name] "" result "" color_map["std"] # If we are not using colorized output, or if we do not know how # to colorize the given result, we should return it unchanged. return result } function report(result, details) { if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) { msg = ": " test_script_name add_test_result(result) } else if (result == "#") { msg = " " test_script_name ":" } else { abort("in function report()") } if (length(details)) msg = msg " " details # Output on console might be colorized. print decorate_result(result) msg # Log the result in the log file too, to help debugging (this is # especially true when said result is a TAP error or "Bail out!"). print result msg | "cat >&3"; } function testsuite_error(error_message) { report("ERROR", "- " error_message) } function handle_tap_result() { details = result_obj["number"]; if (length(result_obj["description"])) details = details " " result_obj["description"] if (plan_seen == LATE_PLAN) { details = details " # AFTER LATE PLAN"; } else if (result_obj["is_unplanned"]) { details = details " # UNPLANNED"; } else if (result_obj["number"] != testno) { details = sprintf("%s # OUT-OF-ORDER (expecting %d)", details, testno); } else if (result_obj["directive"]) { details = details " # " result_obj["directive"]; if (length(result_obj["explanation"])) details = details " " result_obj["explanation"] } report(stringify_result_obj(result_obj), details) } # `skip_reason` should be empty whenever planned > 0. function handle_tap_plan(planned, skip_reason) { planned += 0 # Avoid getting confused if, say, `planned` is "00" if (length(skip_reason) && planned > 0) abort("in function handle_tap_plan()") if (plan_seen) { # Error, only one plan per stream is acceptable. testsuite_error("multiple test plans") return; } planned_tests = planned # The TAP plan can come before or after *all* the TAP results; we speak # respectively of an "early" or a "late" plan. If we see the plan line # after at least one TAP result has been seen, assume we have a late # plan; in this case, any further test result seen after the plan will # be flagged as an error. plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) # If testno > 0, we have an error ("too many tests run") that will be # automatically dealt with later, so do not worry about it here. If # $plan_seen is true, we have an error due to a repeated plan, and that # has already been dealt with above. Otherwise, we have a valid "plan # with SKIP" specification, and should report it as a particular kind # of SKIP result. if (planned == 0 && testno == 0) { if (length(skip_reason)) skip_reason = "- " skip_reason; report("SKIP", skip_reason); } } function extract_tap_comment(line) { if (index(line, diag_string) == 1) { # Strip leading `diag_string` from `line`. line = substr(line, length(diag_string) + 1) # And strip any leading and trailing whitespace left. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) # Return what is left (if any). return line; } return ""; } # When this function is called, we know that line is a TAP result line, # so that it matches the (perl) RE "^(not )?ok\b". function setup_result_obj(line) { # Get the result, and remove it from the line. result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) sub("^(not )?ok[ \t]*", "", line) # If the result has an explicit number, get it and strip it; otherwise, # automatically assign the next test number to it. if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) { match(line, "^[0-9]+") # The final `+ 0` is to normalize numbers with leading zeros. result_obj["number"] = substr(line, 1, RLENGTH) + 0 line = substr(line, RLENGTH + 1) } else { result_obj["number"] = testno } if (plan_seen == LATE_PLAN) # No further test results are acceptable after a "late" TAP plan # has been seen. result_obj["is_unplanned"] = 1 else if (plan_seen && testno > planned_tests) result_obj["is_unplanned"] = 1 else result_obj["is_unplanned"] = 0 # Strip trailing and leading whitespace. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) # This will have to be corrected if we have a "TODO"/"SKIP" directive. result_obj["description"] = line result_obj["directive"] = "" result_obj["explanation"] = "" if (index(line, "#") == 0) return # No possible directive, nothing more to do. # Directives are case-insensitive. rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" # See whether we have the directive, and if yes, where. pos = match(line, rx "$") if (!pos) pos = match(line, rx "[^a-zA-Z0-9_]") # If there was no TAP directive, we have nothing more to do. if (!pos) return # Let`s now see if the TAP directive has been escaped. For example: # escaped: ok \# SKIP # not escaped: ok \\# SKIP # escaped: ok \\\\\# SKIP # not escaped: ok \ # SKIP if (substr(line, pos, 1) == "#") { bslash_count = 0 for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) bslash_count += 1 if (bslash_count % 2) return # Directive was escaped. } # Strip the directive and its explanation (if any) from the test # description. result_obj["description"] = substr(line, 1, pos - 1) # Now remove the test description from the line, that has been dealt # with already. line = substr(line, pos) # Strip the directive, and save its value (normalized to upper case). sub("^[ \t]*#[ \t]*", "", line) result_obj["directive"] = toupper(substr(line, 1, 4)) line = substr(line, 5) # Now get the explanation for the directive (if any), with leading # and trailing whitespace removed. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) result_obj["explanation"] = line } function get_test_exit_message(status) { if (status == 0) return "" if (status !~ /^[1-9][0-9]*$/) abort("getting exit status") if (status < 127) exit_details = "" else if (status == 127) exit_details = " (command not found?)" else if (status >= 128 && status <= 255) exit_details = sprintf(" (terminated by signal %d?)", status - 128) else if (status > 256 && status <= 384) # We used to report an "abnormal termination" here, but some Korn # shells, when a child process die due to signal number n, can leave # in $? an exit status of 256+n instead of the more standard 128+n. # Apparently, both behaviours are allowed by POSIX (2008), so be # prepared to handle them both. See also Austing Group report ID # 0000051 exit_details = sprintf(" (terminated by signal %d?)", status - 256) else # Never seen in practice. exit_details = " (abnormal termination)" return sprintf("exited with status %d%s", status, exit_details) } function write_test_results() { print ":global-test-result: " get_global_test_result() > trs_file print ":recheck: " yn(must_recheck()) > trs_file print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file for (i = 0; i < test_results_index; i += 1) print ":test-result: " test_results_list[i] > trs_file close(trs_file); } BEGIN { ## ------- ## ## SETUP ## ## ------- ## '"$init_colors"' # Properly initialized once the TAP plan is seen. planned_tests = 0 COOKED_PASS = expect_failure ? "XPASS": "PASS"; COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; # Enumeration-like constants to remember which kind of plan (if any) # has been seen. It is important that NO_PLAN evaluates "false" as # a boolean. NO_PLAN = 0 EARLY_PLAN = 1 LATE_PLAN = 2 testno = 0 # Number of test results seen so far. bailed_out = 0 # Whether a "Bail out!" directive has been seen. # Whether the TAP plan has been seen or not, and if yes, which kind # it is ("early" is seen before any test result, "late" otherwise). plan_seen = NO_PLAN ## --------- ## ## PARSING ## ## --------- ## is_first_read = 1 while (1) { # Involutions required so that we are able to read the exit status # from the last input line. st = getline if (st < 0) # I/O error. fatal("I/O error while reading from input stream") else if (st == 0) # End-of-input { if (is_first_read) abort("in input loop: only one input line") break } if (is_first_read) { is_first_read = 0 nextline = $0 continue } else { curline = nextline nextline = $0 $0 = curline } # Copy any input line verbatim into the log file. print | "cat >&3" # Parsing of TAP input should stop after a "Bail out!" directive. if (bailed_out) continue # TAP test result. if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) { testno += 1 setup_result_obj($0) handle_tap_result() } # TAP plan (normal or "SKIP" without explanation). else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) { # The next two lines will put the number of planned tests in $0. sub("^1\\.\\.", "") sub("[^0-9]*$", "") handle_tap_plan($0, "") continue } # TAP "SKIP" plan, with an explanation. else if ($0 ~ /^1\.\.0+[ \t]*#/) { # The next lines will put the skip explanation in $0, stripping # any leading and trailing whitespace. This is a little more # tricky in truth, since we want to also strip a potential leading # "SKIP" string from the message. sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") sub("[ \t]*$", ""); handle_tap_plan(0, $0) } # "Bail out!" magic. # Older versions of prove and TAP::Harness (e.g., 3.17) did not # recognize a "Bail out!" directive when preceded by leading # whitespace, but more modern versions (e.g., 3.23) do. So we # emulate the latter, "more modern" behaviour. else if ($0 ~ /^[ \t]*Bail out!/) { bailed_out = 1 # Get the bailout message (if any), with leading and trailing # whitespace stripped. The message remains stored in `$0`. sub("^[ \t]*Bail out![ \t]*", ""); sub("[ \t]*$", ""); # Format the error message for the bailout_message = "Bail out!" if (length($0)) bailout_message = bailout_message " " $0 testsuite_error(bailout_message) } # Maybe we have too look for dianogtic comments too. else if (comments != 0) { comment = extract_tap_comment($0); if (length(comment)) report("#", comment); } } ## -------- ## ## FINISH ## ## -------- ## # A "Bail out!" directive should cause us to ignore any following TAP # error, as well as a non-zero exit status from the TAP producer. if (!bailed_out) { if (!plan_seen) { testsuite_error("missing test plan") } else if (planned_tests != testno) { bad_amount = testno > planned_tests ? "many" : "few" testsuite_error(sprintf("too %s tests run (expected %d, got %d)", bad_amount, planned_tests, testno)) } if (!ignore_exit) { # Fetch exit status from the last line. exit_message = get_test_exit_message(nextline) if (exit_message) testsuite_error(exit_message) } } write_test_results() exit 0 } # End of "BEGIN" block. ' # TODO: document that we consume the file descriptor 3 :-( } 3>"$log_file" test $? -eq 0 || fatal "I/O or internal error" # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/build-aux/config.sub0000555000076600000240000011004414715040755013501 #!/nix/store/rj7zvmif800bgg3sbznq6g5g438jx104-bash-5.2p37/bin/sh # Configuration validation subroutine script. # Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ | windows-* ) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x"$basic_os" != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. obj= case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 fi ;; *) echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 exit 1 ;; esac case $obj in aout* | coff* | elf* | pe*) ;; '') # empty is fine ;; *) echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2 exit 1 ;; esac # Here we handle the constraint that a (synthetic) cpu and os are # valid only in combination with each other and nowhere else. case $cpu-$os in # The "javascript-unknown-ghcjs" triple is used by GHC; we # accept it here in order to tolerate that, but reject any # variations. javascript-ghcjs) ;; javascript-* | *-ghcjs) echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os-$obj in linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \ | linux-mlibc*- | linux-musl*- | linux-newlib*- \ | linux-relibc*- | linux-uclibc*- ) ;; uclinux-uclibc*- ) ;; managarm-mlibc*- | managarm-kernel*- ) ;; windows*-msvc*-) ;; -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \ | -uclibc*- ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 exit 1 ;; -kernel*- ) echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 exit 1 ;; *-kernel*- ) echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 exit 1 ;; *-msvc*- ) echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 exit 1 ;; kfreebsd*-gnu*- | kopensolaris*-gnu*-) ;; vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) ;; nto-qnx*-) ;; os2-emx-) ;; *-eabi*- | *-gnueabi*-) ;; none--*) # None (no kernel, i.e. freestanding / bare metal), # can be paired with an machine code file format ;; -*-) # Blank kernel with real OS is always fine. ;; --*) # Blank kernel and OS with real machine code file format is always fine. ;; *-*-*) echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: radsecproxy-1.11.1/build-aux/compile0000555000076600000240000001635014715040755013101 #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/build-aux/test-driver0000555000076600000240000001141714715040755013720 #! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2021 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <"$log_file" "$@" >>"$log_file" 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>"$log_file" # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: radsecproxy-1.11.1/debug.h0000644000076600000240000000155514722543325011072 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2010-2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include #define DBG_DBG 8 #define DBG_INFO 16 #define DBG_NOTICE 32 #define DBG_WARN 64 #define DBG_ERR 128 #define LOG_TYPE_DEBUG 0 #define LOG_TYPE_FTICKS 1 void debug_init(char *ident); void debug_set_level(uint8_t level); void debug_timestamp_on(void); void debug_tid_on(void); uint8_t debug_get_level(void); void debug(uint8_t level, char *format, ...); void debugx(int status, uint8_t level, char *format, ...); void debugerrno(int err, uint8_t level, char *format, ...); void debugerrnox(int err, uint8_t level, char *format, ...); int debug_set_destination(char *dest, int log_type); void debug_reopen_log(void); void fticks_debug(const char *format, ...); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/configure.ac0000644000076600000240000000675514724610631012125 dnl Copyright (c) 2006-2010, UNINETT AS dnl Copyright (c) 2010-2013,2016, NORDUnet A/S dnl Copyright (c) 2023, SWITCH dnl See LICENSE for licensing information. AC_INIT([radsecproxy],[1.11.1],[https://radsecproxy.github.io]) AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE AC_PROG_CC AC_PROG_RANLIB AC_CHECK_FUNCS([mallopt]) AC_REQUIRE_AUX_FILE([tap-driver.sh]) AX_BUILD_DATE_EPOCH(RELEASEDATE, %Y-%m-%d) AC_SUBST(RELEASEDATE) m4_version_prereq(2.70, [], [AC_PROG_CC_C99]) if test "$ac_cv_prog_cc_c99" = "no"; then echo "requires C99 compatible compiler" exit -1 fi udp=yes AC_ARG_ENABLE(udp, [ --enable-udp whether to enable UDP transport: yes/no; default yes ], [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then udp=$enableval else echo "--enable-udp argument must be yes or no" exit -1 fi ]) tcp=yes AC_ARG_ENABLE(tcp, [ --enable-tcp whether to enable TCP transport: yes/no; default yes ], [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then tcp=$enableval else echo "--enable-tcp argument must be yes or no" exit -1 fi ]) tls=yes AC_ARG_ENABLE(tls, [ --enable-tls whether to enable TLS (RadSec) transport: yes/no; default yes ], [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then tls=$enableval else echo "--enable-tls argument must be yes or no" exit -1 fi ]) dtls=yes AC_ARG_ENABLE(dtls, [ --enable-dtls whether to enable DTLS transport: yes/no; default yes ], [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then dtls=$enableval else echo "--enable-dtls argument must be yes or no" exit -1 fi ]) AC_CHECK_LIB([nettle], [nettle_sha256_init],, [AC_MSG_ERROR([required library nettle not found])]) # check if we need -lresolv AC_CHECK_LIB([resolv], [inet_aton]) dnl Check if we're on Solaris and set CFLAGS accordingly AC_CANONICAL_TARGET case "${target_os}" in solaris*) TARGET_CFLAGS="-DSYS_SOLARIS -D_POSIX_PTHREAD_SEMANTICS" if test "$GCC" != yes ; then TARGET_CFLAGS="$TARGET_CFLAGS -mt" else TARGET_CFLAGS="$TARGET_CFLAGS -pthreads" fi TARGET_LDFLAGS="-lpthread -lsocket -lnsl" ;; darwin*) TARGET_CFLAGS="-D__APPLE_USE_RFC_3542 -Wno-deprecated-declarations -Wall -pedantic -Wno-long-long -pthread" ;; *) TARGET_CFLAGS="-Wall -pedantic -Wno-long-long -pthread" TARGET_LDFLAGS="" esac dnl Adding enabled options if test "x$udp" = "xyes" ; then echo "UDP transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_UDP" fi if test "x$tcp" = "xyes" ; then echo "TCP transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_TCP" fi if test "x$tls" = "xyes" ; then echo "TLS (RadSec) transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_TLS" fi if test "x$dtls" = "xyes" ; then echo "DTLS transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_DTLS" fi dnl Substitute variables such as sysconfdir AC_CONFIG_FILES([radsecproxy.8 radsecproxy-hash.8 radsecproxy.conf.5]) dnl Expand sysconfdir early to avoid two layers of substitution test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' SYSCONFDIR=`eval echo $sysconfdir` SYSCONFDIR=`eval echo $SYSCONFDIR` AC_SUBST(SYSCONFDIR) AC_SUBST(TARGET_CFLAGS) AC_SUBST(TARGET_LDFLAGS) AX_CHECK_OPENSSL([],AC_MSG_FAILURE([could not locate OpenSSL. Specify its location using --with-openssl=])) AC_CONFIG_FILES([ Makefile tests/Makefile ]) AC_OUTPUT radsecproxy-1.11.1/tools/0000755000076600000240000000000014724611072011042 5radsecproxy-1.11.1/tools/naptr-eduroam.sh0000755000076600000240000000453114452772710014107 #! /bin/sh # Example script! # This script looks up radsec srv records in DNS for the one # realm given as argument, and creates a server template based # on that. It currently ignores weight markers, but does sort # servers on priority marker, lowest number first. # For host command this is column 5, for dig it is column 1. usage() { echo "Usage: ${0} " exit 1 } test -n "${1}" || usage DIGCMD=$(command -v dig) HOSTCMD=$(command -v host) PRINTCMD=$(command -v printf) validate_host() { echo ${@} | tr -d '\n\t\r' | grep -E '^[_0-9a-zA-Z][-._0-9a-zA-Z]*$' } validate_port() { echo ${@} | tr -d '\n\t\r' | grep -E '^[0-9]+$' } dig_it_srv() { ${DIGCMD} +short srv $SRV_HOST | sort -n -k1 | while read line; do set $line ; PORT=$(validate_port $3) ; HOST=$(validate_host $4) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\thost ${HOST%.}:${PORT}\n" fi done } dig_it_naptr() { ${DIGCMD} +short naptr "${REALM}" | grep x-eduroam:radius.tls | sort -n -k1 | while read line; do set $line ; TYPE=$3 ; HOST=$(validate_host $6) if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then SRV_HOST=${HOST%.} dig_it_srv fi done } host_it_srv() { ${HOSTCMD} -t srv $SRV_HOST | sort -n -k5 | while read line; do set $line ; PORT=$(validate_port $7) ; HOST=$(validate_host $8) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\thost ${HOST%.}:${PORT}\n" fi done } host_it_naptr() { ${HOSTCMD} -t naptr "${REALM}" | grep x-eduroam:radius.tls | sort -n -k5 | while read line; do set $line ; TYPE=$7 ; HOST=$(validate_host ${10}) if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then SRV_HOST=${HOST%.} host_it_srv fi done } REALM=$(validate_host ${1}) if [ -z "${REALM}" ]; then echo "Error: realm \"${1}\" failed validation" usage fi if [ -x "${DIGCMD}" ]; then SERVERS=$(dig_it_naptr) elif [ -x "${HOSTCMD}" ]; then SERVERS=$(host_it_naptr) else echo "${0} requires either \"dig\" or \"host\" command." exit 1 fi if [ -n "${SERVERS}" ]; then $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n}\n" exit 0 fi exit 10 # No server found. radsecproxy-1.11.1/tools/radsec-dynsrv.sh0000755000076600000240000000325114452772710014113 #! /bin/sh # Example script! # This script looks up radsec srv records in DNS for the one # realm given as argument, and creates a server template based # on that. It currently ignores weight markers, but does sort # servers on priority marker, lowest number first. # For host command this is column 5, for dig it is column 1. usage() { echo "Usage: ${0} " exit 1 } test -n "${1}" || usage DIGCMD=$(command -v digaaa) HOSTCMD=$(command -v host) PRINTCMD=$(command -v printf) validate_host() { echo ${@} | tr -d '\n\t\r' | grep -E '^[_0-9a-zA-Z][-._0-9a-zA-Z]*$' } validate_port() { echo ${@} | tr -d '\n\t\r' | grep -E '^[0-9]+$' } dig_it() { ${DIGCMD} +short srv "_radsec._tcp.${REALM}" | sort -n -k1 | while read line ; do set $line ; PORT=$(validate_port $3) ; HOST=$(validate_host $4) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\thost ${HOST%.}:${PORT}\n" fi done } host_it() { ${HOSTCMD} -t srv "_radsec._tcp.${REALM}" | sort -n -k5 | while read line ; do set $line ; PORT=$(validate_port $7) ; HOST=$(validate_host $8) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\thost ${HOST%.}:${PORT}\n" fi done } REALM=$(validate_host ${1}) if test -z "${REALM}" ; then echo "Error: realm \"${1}\" failed validation" usage fi if test -x "${DIGCMD}" ; then SERVERS=$(dig_it) elif test -x "${HOSTCMD}" ; then SERVERS=$(host_it) else echo "${0} requires either \"dig\" or \"host\" command." exit 1 fi if test -n "${SERVERS}" ; then $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n}\n" exit 0 fi exit 10 # No server found. radsecproxy-1.11.1/tools/README0000644000076600000240000000270112724361552011645 Mail[1] to the radsecproxy mailing list Wed, 14 Apr 2010 from Stefan Winter explaining the radsec-dynsrv.sh and naptr-eduroam.sh scripts. ------------------------------------------------------------ Hi, the radsec-dynsrv.sh script right now looks up _radsec._tcp.$REALM. For eduroam, the production discovery will rely on S-NAPTRs of "s" type and subsequent SRVs. I have attached a preliminary version of the discovery script which takes this logic into account. It could use some public scrutiny (where "public" might very well evaluate to Kolbjørn Barmen, who wrote the SRV script and knows much more about bash scripting than I do *cough cough*). As with the other script, you call naptr-eduroam.sh If you need a test case, the DNS domain restena.lu has the NAPTR and the SRV record live in place. On my system, you get: > ./naptr-eduroam.sh restena.lu server dynamic_radsec.restena.lu { host radius-1.restena.lu:2083 type TLS } with our live DNS data (radius-1.restena.lu isn't really production-ready yet though). If you're curious, the S-NAPTR for eduroam right now is x-eduroam:radius.tls with a possibility of a later IETF allocation of either aaa:radius.tls (probable) eduroam:radius.tls (wishful thinking) , in which case changing the script to use the new ones is trivial. Greetings, Stefan Winter ------------------------------------------------------------ [1] https://postlister.uninett.no/sympa/arc/radsecproxy/2010-04/msg00011.html radsecproxy-1.11.1/INSTALL0000644000076600000240000002713614706704155010671 Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 6. Often, you can also type `make uninstall' to remove the installed files again. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *Note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. radsecproxy-1.11.1/tls.h0000644000076600000240000000030313320713715010567 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ const struct protodefs *tlsinit(uint8_t h); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/util.c0000644000076600000240000002715114722543325010754 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2016, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "util.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include char *stringcopy(const char *s, int len) { char *r; if (!s) return NULL; if (!len) len = strlen(s); r = malloc(len + 1); if (!r) debugx(1, DBG_ERR, "stringcopy: malloc failed"); memcpy(r, s, len); r[len] = '\0'; return r; } /** * @brief verify if str is properly utf-8 encoded * * @param str string to verify * @param str_len length of the string without terminating null. * @return int 1 if valid utf-8, 0 otherwise */ int verifyutf8(const unsigned char *str, size_t str_len) { const unsigned char *byte; size_t charlen; for (byte = str; byte < str + str_len; byte++) { if (*byte == 0x00) return 0; if ((*byte & 0x80) == 0x00) { if (*byte < 0x20 || *byte == 0x7F) return 0; continue; } if (*byte > 0xF4) return 0; if ((*byte & 0xE0) == 0xC0) { if ((*byte & 0xFE) == 0xC0) return 0; charlen = 2; } else if ((*byte & 0xF0) == 0xE0) charlen = 3; else if ((*byte & 0xF8) == 0xF0) charlen = 4; else return 0; if (byte + charlen - 1 >= str + str_len) return 0; if (charlen == 2 && *byte == 0xC2 && *(byte + 1) < 0xA0) return 0; if (charlen == 3) { if (*byte == 0xE0 && (*(byte + 1) & 0xE0) == 0x80) return 0; if (*byte == 0xED && (*(byte + 1) & 0xE0) == 0xA0) return 0; } if (charlen == 4) { if (*byte == 0xF0 && (*(byte + 1) & 0xF0) == 0x80) return 0; if (*byte == 0xF4 && (*(byte + 1) & 0xF0) != 0x80) return 0; } while (--charlen) if ((*(++byte) & 0xC0) != 0x80) return 0; } return 1; } void printfchars(char *prefixfmt, char *prefix, char *charfmt, uint8_t *chars, int len) { int i; unsigned char *s = (unsigned char *)chars; if (prefix) printf(prefixfmt ? prefixfmt : "%s: ", prefix); for (i = 0; i < len; i++) printf(charfmt ? charfmt : "%c", s[i]); printf("\n"); } void port_set(struct sockaddr *sa, uint16_t port) { switch (sa->sa_family) { case AF_INET: ((struct sockaddr_in *)sa)->sin_port = htons(port); break; case AF_INET6: ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); break; } } struct sockaddr *addr_copy(struct sockaddr *in) { struct sockaddr *out = NULL; switch (in->sa_family) { case AF_INET: out = malloc(sizeof(struct sockaddr_in)); if (out == NULL) return NULL; *(struct sockaddr_in *)out = *(struct sockaddr_in *)in; break; case AF_INET6: out = malloc(sizeof(struct sockaddr_in6)); if (out == NULL) return NULL; *(struct sockaddr_in6 *)out = *(struct sockaddr_in6 *)in; break; } assert(out); #ifdef SIN6_LEN out->sa_len = in->sa_len; #endif return out; } const char *addr2string(struct sockaddr *addr, char *buf, size_t len) { struct sockaddr_in6 *sa6; struct sockaddr_in sa4; if (addr->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)addr; if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { memset(&sa4, 0, sizeof(sa4)); sa4.sin_family = AF_INET; sa4.sin_port = sa6->sin6_port; memcpy(&sa4.sin_addr, &sa6->sin6_addr.s6_addr[12], 4); addr = (struct sockaddr *)&sa4; } } if (getnameinfo(addr, SOCKADDRP_SIZE(addr), buf, len, NULL, 0, NI_NUMERICHOST)) { debug(DBG_WARN, "getnameinfo failed"); return "getnameinfo_failed"; } return buf; } /* Disable the "Don't Fragment" bit for UDP sockets. It is set by default, which may cause an "oversized" RADIUS packet to be discarded on first attempt (due to Path MTU discovery). */ void disable_DF_bit(int socket, struct addrinfo *res) { if ((res->ai_family == AF_INET) && (res->ai_socktype == SOCK_DGRAM)) { #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) /* * Turn off Path MTU discovery on IPv4/UDP sockets, Linux variant. */ int r, action; debug(DBG_INFO, "disable_DF_bit: disabling DF bit (Linux variant)"); action = IP_PMTUDISC_DONT; r = setsockopt(socket, IPPROTO_IP, IP_MTU_DISCOVER, &action, sizeof(action)); if (r == -1) debug(DBG_WARN, "Failed to set IP_MTU_DISCOVER"); #else debug(DBG_INFO, "Non-Linux platform, unable to unset DF bit for UDP. You should check with tcpdump whether radsecproxy will send its UDP packets with DF bit set!"); #endif } } void enable_keepalive(int socket) { int optval; socklen_t optlen = sizeof(optval); #if !defined(TCP_KEEPCNT) || !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL) debug(DBG_NOTICE, "TCP Keepalive feature might be limited on this platform"); #else optval = 3; if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPCNT failed"); } optval = 10; if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPIDLE %d failed", optval); } optval = 10; if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPINTVL failed"); } #endif optval = 1; if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt SO_KEEPALIVE failed"); } } int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse) { int s, on = 1; struct addrinfo *res; for (res = addrinfo; res; res = res->ai_next) { if (family != AF_UNSPEC && family != res->ai_family) continue; s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { debugerrno(errno, DBG_WARN, "bindtoaddr: socket creation failed"); continue; } disable_DF_bit(s, res); if (reuse) if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "Failed to set SO_REUSEADDR"); #ifdef IPV6_V6ONLY if (family == AF_INET6) if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "Failed to set IPV6_V6ONLY"); #endif if (!bind(s, res->ai_addr, res->ai_addrlen)) return s; debug(DBG_WARN, "bindtoaddr: bind failed"); close(s); } return -1; } int connectnonblocking(int s, const struct sockaddr *addr, socklen_t addrlen, int timeout) { int origflags, r = -1, sockerr = 0; socklen_t errlen = sizeof(sockerr); struct pollfd fds[1]; origflags = fcntl(s, F_GETFL, 0); if (origflags == -1) { debugerrno(errno, DBG_WARN, "Failed to get flags"); return -1; } if (fcntl(s, F_SETFL, origflags | O_NONBLOCK) == -1) { debugerrno(errno, DBG_WARN, "Failed to set O_NONBLOCK"); return -1; } if (!connect(s, addr, addrlen)) { r = 0; goto exit; } if (errno != EINPROGRESS) goto exit; fds[0].fd = s; fds[0].events = POLLOUT; if (poll(fds, 1, timeout * 1000) < 1) goto exit; if (fds[0].revents & POLLERR) { if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &errlen)) debug(DBG_WARN, "Connection failed: %s", strerror(sockerr)); else debug(DBG_WARN, "Connection failed: unknown error"); } else if (fds[0].revents & POLLHUP) { debug(DBG_WARN, "Connect error: hang up"); } else if (fds[0].revents & POLLNVAL) { debug(DBG_WARN, "Connect error: fd not open"); } else if (fds[0].revents & POLLOUT) { debug(DBG_DBG, "Connection up"); r = 0; } exit: if (fcntl(s, F_SETFL, origflags) == -1) debugerrno(errno, DBG_WARN, "Failed to set original flags back"); return r; } int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout) { int s; struct addrinfo *res; s = -1; if (timeout) { if (addrinfo && addrinfo->ai_next && timeout > 5) timeout = 5; } for (res = addrinfo; res; res = res->ai_next) { s = bindtoaddr(src, res->ai_family, 1); if (s < 0) { debug(DBG_WARN, "connecttoserver: socket failed"); continue; } if ((timeout ? connectnonblocking(s, res->ai_addr, res->ai_addrlen, timeout) : connect(s, res->ai_addr, res->ai_addrlen)) == 0) break; debug(DBG_WARN, "connecttoserver: connect failed"); close(s); s = -1; } return s; } void accepttcp(int socket, void handler(int)) { int s; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); char tmp[INET6_ADDRSTRLEN]; if (getsockname(socket, (struct sockaddr *)&from, &fromlen) != 0) debugerrno(errno, DBG_ERR, "accepttcp: getsockname failed"); if (listen(socket, 128) != 0) { debugerrno(errno, DBG_ERR, "accepttcp: listen on %s failed", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); goto exit; } debug(DBG_DBG, "accepttcp: listening on %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); for (;;) { s = accept(socket, (struct sockaddr *)&from, &fromlen); if (s < 0) { switch (errno) { case EBADF: case EFAULT: case EINVAL: case ENOTSOCK: case EOPNOTSUPP: case EPERM: /*non-recoverable errors, exit*/ debugerrno(errno, DBG_WARN, "accepttcp: accept failed, exiting"); goto exit; case ECONNABORTED: break; default: debugerrno(errno, DBG_WARN, "accepttcp: accept failed, trying again later"); sleep(1); } continue; } handler(s); } exit: close(socket); } uint32_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry) { struct timeval now; gettimeofday(&now, NULL); if (attempt_start.tv_sec < last_success.tv_sec || attempt_start.tv_sec > now.tv_sec) { debug(DBG_WARN, "connect_wait: invalid timers detected!"); return 60; } if (now.tv_sec - last_success.tv_sec < 30) return 30 - (attempt_start.tv_sec - last_success.tv_sec); if (firsttry) return 0; if (now.tv_sec - attempt_start.tv_sec < 2) return 2; if (now.tv_sec - attempt_start.tv_sec > 60) return 60; return now.tv_sec - attempt_start.tv_sec; } /** * @brief Skip (discard) dgram frame at front of queue * * @param socket the dgram socket */ void sock_dgram_skip(int socket) { uint8_t dummy; if (recv(socket, &dummy, sizeof(dummy), MSG_DONTWAIT) == -1) debug(DBG_ERR, "sock_dgram_skip: recv failed - %s", strerror(errno)); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/LICENSE0000644000076600000240000000320013556476612010635 Radsecproxy is distributed under this license: * Copyright (c) 2007-2010, UNINETT AS * Copyright (c) 2010-2017, NORDUnet A/S * Copyright (c) 2018, SWITCH * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. radsecproxy-1.11.1/configure0000755000076600000240000054624114724611067011551 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for radsecproxy 1.11.1. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case e in #( e) case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else case e in #( e) exitcode=1; echo positional parameters were not saved. ;; esac fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else case e in #( e) as_have_required=no ;; esac fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi ;; esac fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: https://radsecproxy.github.io about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi ;; esac fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' t clear :clear s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='radsecproxy' PACKAGE_TARNAME='radsecproxy' PACKAGE_VERSION='1.11.1' PACKAGE_STRING='radsecproxy 1.11.1' PACKAGE_BUGREPORT='https://radsecproxy.github.io' PACKAGE_URL='' ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES PKG_CONFIG TARGET_LDFLAGS TARGET_CFLAGS SYSCONFDIR RELEASEDATE RANLIB am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V CSCOPE ETAGS CTAGS am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_udp enable_tcp enable_tls enable_dtls with_openssl ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: '$ac_option' Try '$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: '$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: '$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF 'configure' configures radsecproxy 1.11.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print 'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for '--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, 'make install' will install all the files in '$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify an installation prefix other than '$ac_default_prefix' using '--prefix', for instance '--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/radsecproxy] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of radsecproxy 1.11.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-udp whether to enable UDP transport: yes/no; default yes --enable-tcp whether to enable TCP transport: yes/no; default yes --enable-tls whether to enable TLS (RadSec) transport: yes/no; default yes --enable-dtls whether to enable DTLS transport: yes/no; default yes Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-openssl=DIR root of the OpenSSL directory Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by 'configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF radsecproxy configure 1.11.1 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (void); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (void); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by radsecproxy $as_me 1.11.1, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See 'config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (char **p, int i) { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* C89 style stringification. */ #define noexpand_stringify(a) #a const char *stringified = noexpand_stringify(arbitrary+token=sequence); /* C89 style token pasting. Exercises some of the corner cases that e.g. old MSVC gets wrong, but not very hard. */ #define noexpand_concat(a,b) a##b #define expand_concat(a,b) noexpand_concat(a,b) extern int vA; extern int vbee; #define aye A #define bee B int *pvA = &expand_concat(v,aye); int *pvbee = &noexpand_concat(v,bee); /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' /* Does the compiler advertise C99 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif // See if C++-style comments work. #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); extern void free (void *); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Work around memory leak warnings. free (ia); // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' /* Does the compiler advertise C11 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Auxiliary files required by this configure script. ac_aux_files="tap-driver.sh compile missing install-sh config.guess config.sub" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}/build-aux" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;; esac fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 printf %s "checking target system type... " >&6; } if test ${ac_cv_target+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5 fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 printf "%s\n" "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir ;; esac fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was 's,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ *'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS ;; esac fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use plain mkdir -p, # in the hope it doesn't have the bugs of ancient mkdir. MKDIR_P='mkdir -p' fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else case e in #( e) cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make ;; esac fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else case e in #( e) if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='radsecproxy' VERSION='1.11.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi if test -z "$ETAGS"; then ETAGS=etags fi if test -z "$CSCOPE"; then CSCOPE=cscope fi # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See 'config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'. # So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an '-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else case e in #( e) ac_file='' ;; esac fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See 'config.log' for more details" "$LINENO" 5; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both 'conftest.exe' and 'conftest' are 'present' (well, observable) # catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will # work properly (i.e., refer to 'conftest.exe'), while it won't with # 'rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); if (!f) return 1; return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use '--host'. See 'config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext \ conftest.o conftest.obj conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest.$ac_cv_objext conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else case e in #( e) CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test ${enable_dependency_tracking+y} then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi ac_fn_c_check_func "$LINENO" "mallopt" "ac_cv_func_mallopt" if test "x$ac_cv_func_mallopt" = xyes then : printf "%s\n" "#define HAVE_MALLOPT 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5 printf %s "checking for build time... " >&6; } ax_date_fmt="%Y-%m-%d" if test x"$SOURCE_DATE_EPOCH" = x then : RELEASEDATE=`date "+$ax_date_fmt"` else case e in #( e) ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \ || date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null` if test x"$ax_build_date" = x then : as_fn_error $? "malformed SOURCE_DATE_EPOCH" "$LINENO" 5 else case e in #( e) RELEASEDATE=$ax_build_date ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RELEASEDATE" >&5 printf "%s\n" "$RELEASEDATE" >&6; } if test "$ac_cv_prog_cc_c99" = "no"; then echo "requires C99 compatible compiler" exit -1 fi udp=yes # Check whether --enable-udp was given. if test ${enable_udp+y} then : enableval=$enable_udp; if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then udp=$enableval else echo "--enable-udp argument must be yes or no" exit -1 fi fi tcp=yes # Check whether --enable-tcp was given. if test ${enable_tcp+y} then : enableval=$enable_tcp; if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then tcp=$enableval else echo "--enable-tcp argument must be yes or no" exit -1 fi fi tls=yes # Check whether --enable-tls was given. if test ${enable_tls+y} then : enableval=$enable_tls; if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then tls=$enableval else echo "--enable-tls argument must be yes or no" exit -1 fi fi dtls=yes # Check whether --enable-dtls was given. if test ${enable_dtls+y} then : enableval=$enable_dtls; if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then dtls=$enableval else echo "--enable-dtls argument must be yes or no" exit -1 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for nettle_sha256_init in -lnettle" >&5 printf %s "checking for nettle_sha256_init in -lnettle... " >&6; } if test ${ac_cv_lib_nettle_nettle_sha256_init+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lnettle $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char nettle_sha256_init (void); int main (void) { return nettle_sha256_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_nettle_nettle_sha256_init=yes else case e in #( e) ac_cv_lib_nettle_nettle_sha256_init=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nettle_nettle_sha256_init" >&5 printf "%s\n" "$ac_cv_lib_nettle_nettle_sha256_init" >&6; } if test "x$ac_cv_lib_nettle_nettle_sha256_init" = xyes then : printf "%s\n" "#define HAVE_LIBNETTLE 1" >>confdefs.h LIBS="-lnettle $LIBS" else case e in #( e) as_fn_error $? "required library nettle not found" "$LINENO" 5 ;; esac fi # check if we need -lresolv { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_aton in -lresolv" >&5 printf %s "checking for inet_aton in -lresolv... " >&6; } if test ${ac_cv_lib_resolv_inet_aton+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char inet_aton (void); int main (void) { return inet_aton (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_resolv_inet_aton=yes else case e in #( e) ac_cv_lib_resolv_inet_aton=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_inet_aton" >&5 printf "%s\n" "$ac_cv_lib_resolv_inet_aton" >&6; } if test "x$ac_cv_lib_resolv_inet_aton" = xyes then : printf "%s\n" "#define HAVE_LIBRESOLV 1" >>confdefs.h LIBS="-lresolv $LIBS" fi case "${target_os}" in solaris*) TARGET_CFLAGS="-DSYS_SOLARIS -D_POSIX_PTHREAD_SEMANTICS" if test "$GCC" != yes ; then TARGET_CFLAGS="$TARGET_CFLAGS -mt" else TARGET_CFLAGS="$TARGET_CFLAGS -pthreads" fi TARGET_LDFLAGS="-lpthread -lsocket -lnsl" ;; darwin*) TARGET_CFLAGS="-D__APPLE_USE_RFC_3542 -Wno-deprecated-declarations -Wall -pedantic -Wno-long-long -pthread" ;; *) TARGET_CFLAGS="-Wall -pedantic -Wno-long-long -pthread" TARGET_LDFLAGS="" esac if test "x$udp" = "xyes" ; then echo "UDP transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_UDP" fi if test "x$tcp" = "xyes" ; then echo "TCP transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_TCP" fi if test "x$tls" = "xyes" ; then echo "TLS (RadSec) transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_TLS" fi if test "x$dtls" = "xyes" ; then echo "DTLS transport enabled" TARGET_CFLAGS="$TARGET_CFLAGS -DRADPROT_DTLS" fi ac_config_files="$ac_config_files radsecproxy.8 radsecproxy-hash.8 radsecproxy.conf.5" test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' SYSCONFDIR=`eval echo $sysconfdir` SYSCONFDIR=`eval echo $SYSCONFDIR` found=false # Check whether --with-openssl was given. if test ${with_openssl+y} then : withval=$with_openssl; case "$withval" in "" | y | ye | yes | n | no) as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5 ;; *) ssldirs="$withval" ;; esac else case e in #( e) # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$PKG_CONFIG"; then ac_cv_prog_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_PKG_CONFIG="${ac_tool_prefix}pkg-config" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi PKG_CONFIG=$ac_cv_prog_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_PKG_CONFIG"; then ac_ct_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_PKG_CONFIG"; then ac_cv_prog_ac_ct_PKG_CONFIG="$ac_ct_PKG_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_PKG_CONFIG="pkg-config" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_PKG_CONFIG=$ac_cv_prog_ac_ct_PKG_CONFIG if test -n "$ac_ct_PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PKG_CONFIG" >&5 printf "%s\n" "$ac_ct_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_ct_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_prog_PKG_CONFIG" fi if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi ;; esac fi # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for include/openssl/ssl.h in $ssldir" >&5 printf %s "checking for include/openssl/ssl.h in $ssldir... " >&6; } if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } break else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5 printf %s "checking whether compiling and linking against OpenSSL works... " >&6; } echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5 save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { SSL_new(NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "could not locate OpenSSL. Specify its location using --with-openssl= See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ac_config_files="$ac_config_files Makefile tests/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # 'ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* 'ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # 'set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # 'set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[][ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 printf "%s\n" "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by radsecproxy $as_me 1.11.1, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ '$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ radsecproxy config.status 1.11.1 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" Copyright (C) 2023 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: '$1' Try '$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "radsecproxy.8") CONFIG_FILES="$CONFIG_FILES radsecproxy.8" ;; "radsecproxy-hash.8") CONFIG_FILES="$CONFIG_FILES radsecproxy-hash.8" ;; "radsecproxy.conf.5") CONFIG_FILES="$CONFIG_FILES radsecproxy.conf.5" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to '$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with './config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain ':'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is 'configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when '$srcdir' = '.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See 'config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi radsecproxy-1.11.1/radsecproxy.8.in0000644000076600000240000000557214452772710012701 .TH radsecproxy 8 "@RELEASEDATE@" "@PACKAGE_STRING@" .SH "NAME" radsecproxy - a generic RADIUS proxy that provides both RADIUS UDP and TCP/TLS (RadSec) transport. .SH "SYNOPSIS" .HP 12 radsecproxy [\-c \fIconfigfile\fR] [\-d \fIdebuglevel\fR] [\-f] [\-i \fIpidfile\fR] [\-p] [\-v] .sp .SH "DESCRIPTION" radsecproxy is a \fBgeneric RADIUS proxy\fR that in addition to to usual \fBRADIUS UDP\fR transport, also supports \fBTLS (RadSec)\fR. The aim is for the proxy to have sufficient features to be flexible, while at the same time to be small, efficient and easy to configure. The proxy was initially made to be able to deploy \fBRadSec\fR (RADIUS over TLS) so that all RADIUS communication across network links could be done using TLS, without modifying existing RADIUS software. This can be done by running this proxy on the same host as an existing RADIUS server or client, and configure the existing client/server to talk to localhost (the proxy) rather than other clients and servers directly. There are however other situations where a RADIUS proxy might be useful. Some people deploy RADIUS topologies where they want to route RADIUS messages to the right server. The nodes that do purely routing could be using a proxy. Some people may also wish to deploy a proxy on a site boundary. Since the proxy \fBsupports both IPv4 and IPv6\fR, it could also be used to allow communication in cases where some RADIUS nodes use only IPv4 and some only IPv6. .SH "OPTIONS" .TP .B \-f Run in foreground. .br By specifying this option, the proxy will run in foreground mode. That is, it won't detach. Also all logging will be done to stderr. .TP .B \-d \fIdebuglevel\fR This specifies the debug level. It must be set to 1, 2, 3, 4 or 5, where 1 logs only serious errors, and 5 logs everything. The default is 2 which logs errors, warnings and a few informational messages. .TP .B \-p Pretend .br The proxy reads configuration files and performs initialisation as usual, but exits prior to creating any sockets. It will return different exit codes depending on whether the configuration files are okay. This may be used to verify configuration files, and can be done while another instance is running. .TP .B \-v Print version and exit. .TP .B \-c \fIconfigfile\fR This option allows you to specify which config file to use. This is useful if you want to use a config file that is not in any of the default locations. .TP .B \-i \fIpidfile\fR This option tells the proxy to create a PID file with the specified path. .SH "SIGNALS" The proxy generally exits on all signals. The exceptions are listed below. .TP .B SIGHUP .br When logging to a file, this signal forces a reopen of the log file. .br When using TLS or DTLS, reload certificate CRLs. .TP .B SIGPIPE .br This signal is ignored. .SH "FILES" .TP .B @SYSCONFDIR@/radsecproxy.conf .sp The default configuration file. .SH "SEE ALSO" radsecproxy.conf(5), radsecproxy-hash(8) radsecproxy-1.11.1/hostport.c0000644000076600000240000002756314722543325011670 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2012,2016 NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "hostport.h" #include "debug.h" #include "util.h" #include #include #include #include void freehostport(struct hostportres *hp) { if (hp) { free(hp->host); free(hp->port); if (hp->addrinfo) freeaddrinfo(hp->addrinfo); free(hp); } } static int parsehostport(struct hostportres *hp, char *hostport, char *default_port) { char *p, *field; int ipv6 = 0; if (!hostport) { hp->port = default_port ? stringcopy(default_port, 0) : NULL; return 1; } p = hostport; /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */ if (*p == '[') { p++; field = p; while (*p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n') p++; if (*p != ']') { debug(DBG_ERR, "no ] matching initial ["); return 0; } ipv6 = 1; } else { field = p; while (*p && *p != ':' && *p != '/' && *p != ' ' && *p != '\t' && *p != '\n') p++; } if (field == p) { debug(DBG_ERR, "missing host/address"); return 0; } hp->host = stringcopy(field, p - field); if (ipv6) { p++; if (*p && *p != ':' && *p != '/' && *p != ' ' && *p != '\t' && *p != '\n') { debug(DBG_ERR, "unexpected character after ]"); return 0; } } if (*p == ':') { /* port number or service name is specified */; field = ++p; while (*p && *p != ' ' && *p != '\t' && *p != '\n') p++; if (field == p) { debug(DBG_ERR, "syntax error, : but no following port"); return 0; } hp->port = stringcopy(field, p - field); } else hp->port = default_port ? stringcopy(default_port, 0) : NULL; return 1; } struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok) { struct hostportres *hp; char *slash, *s; int plen; hp = malloc(sizeof(struct hostportres)); if (!hp) { debug(DBG_ERR, "resolve_newhostport: malloc failed"); goto errexit; } memset(hp, 0, sizeof(struct hostportres)); if (!parsehostport(hp, hostport, default_port)) goto errexit; if (hp->host && !strcmp(hp->host, "*")) { free(hp->host); hp->host = NULL; } slash = hostport ? strchr(hostport, '/') : NULL; if (slash) { if (!prefixok) { debug(DBG_WARN, "newhostport: prefix not allowed here (%s)", hp->host); goto errexit; } s = slash + 1; if (!*s) { debug(DBG_WARN, "newhostport: prefix length must be specified after the / in %s", hp->host); goto errexit; } for (; *s; s++) if (*s < '0' || *s > '9') { debug(DBG_WARN, "newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); goto errexit; } plen = atoi(slash + 1); if (plen < 0 || plen > 128) { debug(DBG_WARN, "newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); goto errexit; } hp->prefixlen = plen; } else hp->prefixlen = 255; return hp; errexit: freehostport(hp); return NULL; } int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passive) { struct addrinfo hints, *res; char tmp[INET6_ADDRSTRLEN], *buf = NULL; size_t numaddr = 0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = socktype; hints.ai_family = af; if (passive) hints.ai_flags = AI_PASSIVE; if (!hp->host && !hp->port) { /* getaddrinfo() doesn't like host and port to be NULL */ if (getaddrinfo(hp->host, "1812" /* can be anything */, &hints, &hp->addrinfo)) { debug(DBG_WARN, "resolvehostport: can't resolve (null) port (null)"); goto errexit; } for (res = hp->addrinfo; res; res = res->ai_next) port_set(res->ai_addr, 0); } else { if (hp->prefixlen != 255) hints.ai_flags |= AI_NUMERICHOST; if (getaddrinfo(hp->host, hp->port, &hints, &hp->addrinfo)) { debug(DBG_WARN, "resolvehostport: can't resolve %s port %s", hp->host ? hp->host : "(null)", hp->port ? hp->port : "(null)"); goto errexit; } if (hp->prefixlen != 255) { switch (hp->addrinfo->ai_family) { case AF_INET: if (hp->prefixlen > 32) { debug(DBG_WARN, "resolvehostport: prefix length must be <= 32 in %s", hp->host); goto errexit; } break; case AF_INET6: break; default: debug(DBG_WARN, "resolvehostport: prefix must be IPv4 or IPv6 in %s", hp->host); goto errexit; } } } for (res = hp->addrinfo; res; res = res->ai_next) { if (res->ai_addr) numaddr++; } if (numaddr) { if (!(buf = calloc(numaddr, INET6_ADDRSTRLEN + 2))) { debug(DBG_ERR, "resolvehostport: calloc failed"); return 1; } for (res = hp->addrinfo; res; res = res->ai_next) { if (!res->ai_addr) continue; strcat(buf, addr2string(res->ai_addr, tmp, sizeof(tmp))); if (res->ai_next) strcat(buf, ", "); } } debug(DBG_DBG, "%s: %s -> %s", __func__, (hp->host ? hp->host : "(src info not available)"), (buf ? buf : "(dst info not available)")); free(buf); return 1; errexit: if (hp->addrinfo) freeaddrinfo(hp->addrinfo); return 0; } int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok) { struct hostportres *hp; int i; if (!*hostports) { *hostports = list_create(); if (!*hostports) { debug(DBG_ERR, "addhostport: malloc failed"); return 0; } } for (i = 0; hostport[i]; i++) { hp = newhostport(hostport[i], portdefault, prefixok); if (!hp) return 0; if (!list_push(*hostports, hp)) { freehostport(hp); debug(DBG_ERR, "addhostport: malloc failed"); return 0; } } return 1; } void freehostports(struct list *hostports) { struct hostportres *hp; while ((hp = (struct hostportres *)list_shift(hostports))) freehostport(hp); list_destroy(hostports); } int resolvehostports(struct list *hostports, int af, int socktype) { struct list_node *entry; struct hostportres *hp; for (entry = list_first(hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; if (!hp->addrinfo && !resolvehostport(hp, af, socktype, 0)) return 0; } return 1; } struct addrinfo *resolvepassiveaddrinfo(char **hostport, int af, char *default_port, int socktype) { struct addrinfo *ai = NULL, *last_ai = NULL; int i; char *any[2] = {"*", NULL}; if (!hostport) hostport = any; for (i = 0; hostport[i]; i++) { struct hostportres *hp = newhostport(hostport[i], default_port, 0); if (hp && resolvehostport(hp, af, socktype, 1)) { if (!ai) { ai = last_ai = hp->addrinfo; } else { last_ai->ai_next = hp->addrinfo; } while (last_ai->ai_next) last_ai = last_ai->ai_next; hp->addrinfo = NULL; } freehostport(hp); } return ai; } /* returns 1 if the len first bits are equal, else 0 */ static int prefixmatch(void *a1, void *a2, uint8_t len) { static uint8_t mask[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; uint8_t r, l = len / 8; if (l && memcmp(a1, a2, l)) return 0; r = len % 8; if (!r) return 1; return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]); } int _internal_addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t prefixlen, uint8_t checkport, struct hostportres **hpreturn) { struct sockaddr_in6 *sa6 = NULL; struct in_addr *a4 = NULL; struct addrinfo *res; struct list_node *entry; struct hostportres *hp = NULL; if (addr->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)addr; if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12]; sa6 = NULL; } } else a4 = &((struct sockaddr_in *)addr)->sin_addr; for (entry = list_first(hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; for (res = hp->addrinfo; res; res = res->ai_next) { if (hp->prefixlen >= (res->ai_family == AF_INET ? 32 : 128) && prefixlen >= (a4 ? 32 : 128)) { if ((a4 && res->ai_family == AF_INET && !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4) && (!checkport || ((struct sockaddr_in *)res->ai_addr)->sin_port == ((struct sockaddr_in *)addr)->sin_port)) || (sa6 && res->ai_family == AF_INET6 && !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) && (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port == ((struct sockaddr_in6 *)addr)->sin6_port))) { if (hpreturn) *hpreturn = hp; return 1; } } else if (hp->prefixlen <= prefixlen) { if ((a4 && res->ai_family == AF_INET && prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, hp->prefixlen)) || (sa6 && res->ai_family == AF_INET6 && prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen))) { if (hpreturn) *hpreturn = hp; return 1; } } } } return 0; } int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t checkport) { struct list_node *entry; struct hostportres *match; struct addrinfo *res; for (entry = list_first(matchhostports); entry; entry = list_next(entry)) { match = (struct hostportres *)entry->data; for (res = match->addrinfo; res; res = res->ai_next) { if (_internal_addressmatches(hostports, res->ai_addr, match->prefixlen, checkport, NULL)) return 1; } } return 0; } int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport, struct hostportres **hp) { return _internal_addressmatches(hostports, addr, 255, checkport, hp); } int connecttcphostlist(struct list *hostports, struct addrinfo *src, struct hostportres **hpreturn) { int s; struct list_node *entry; struct hostportres *hp = NULL; for (entry = list_first(hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port); if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) { debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port); if (hpreturn) *hpreturn = hp; return s; } } debug(DBG_ERR, "connecttcphostlist: failed"); return -1; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/ChangeLog0000644000076600000240000004017414724610570011404 2024-12-06 1.11.1 Bug Fixes: - Fix wrong DN in certificate request (#154) - Fix memory leak when using SIGHUP - Fix exit when dyndisc script returns illegal PSKkey - Fix logging during config check - Fix invalid realm configs are ignored - Fix default tls block selection Misc: - Improve message-authenticator logging 2024-07-05 1.11.0 New features: - TLS-PSK (#112) - Long hex-strings in config - Reload complete TLS context on SIGHUP, reload client/server cert and key (#76) - Implement SSLKEYLOGFILE mechanism - Options to require Message-Authenticator Misc: - Re-verify certificates on SIGHUP and terminate invalid connections (#5) - Implement recommendations for deprecating insecure transports (#114) - verify EAP message content length (#128) - Close connection on radius attribute decode errors Bug Fixes: - Fix correct secret for DTLS (radius/dtls) - Fix infinite loop when listening on tcp socket fails - Fix crashes under high load (#75, #109, #129) 2024-05-02 1.10.1 Bug Fixes: - Fix tcp connection not closed after idle timeout - Fix tls/dtls logging (#127, #132) - Fix dynamic connection not re-established after timeout if both auth- and accounting server are dynamically resolved (#131). - Fix error in dyndisc script result might cause radsecproxy to exit. - Fix some TLS config errors not reported at startup - Fix referencing non-existant rewrite passed without error Misc: - Add Message-Authenticator to requests if missing 2023-05-26 1.10.0 New features: - Native dynamic discovery for NAPTR and SRV records (#2, #83) - Optionally log accounting requests when respoinding directly (#72) - SNI support for outgoing connections (#90) - Optionally specify server name for certificate name check (#106) - Manual MTU setting for DTLS on non-linux platforms Misc: - Don't require server type to be set by dyndisc scripts - Improve locating openssl lib using pkg-config Bug Fixes: - Fix radius message length handling 2023-05-02 1.9.3 Bug Fixes: - Fix shutdown TLS connection on malformed radius message (#122) - Fix handling of lost requests in DTLS - Fix flush requests when dyndisc fails 2023-01-23 1.9.2 Bug Fixes: - Fix potential segfault in tcp log message - Fix DTLS over IPv6 - Fix SSL shutdown/EOF for openssl 3.x (#108) 2021-10-25 1.9.1 Misc: - OpenSSL 3.0 compatibility (#70) Bug Fixes: - Fix refused startup with openssl <1.1 (#82) - Fix compiler issue for Fedora 33 on s390x (#84) - Fix small memory leak in config parser - Fix lazy certificate check when connecting to TLS servers - Fix connect is aborted if first host in list has invalid certificate - Fix setstacksize for glibc 2.34 (#91) - Fix system defaults/settings for TLS version not honored (#92) 2021-05-28 1.9.0 New features: - Accept multiple source* configs for IPv4/v6 - Specify source per server - User configurable cipher-list and ciphersuites - User configurable TLS versions - Config option for DH-file - Add rID and otherName options to certifcateAttributeCheck - Allow multiple matchCertificateAttribute - Option to start dynamic server in blocking mode Misc: - Move radsecproxy manpage to section 8 - Log CUI and operator-name if present - Log CN for incomming TLS connections Bug Fixes: - Fix overlapping log lines - Fix memory leak in logging - Fix dynidsc example scripts input validation (CVE-2021-32642) 2020-08-06 1.8.2 Bug fixes: - Fix wrong config-unhexing if %25 (%) occurs - Fix compatibility with GCC 10 (#63) - Fix spelling in manpage - Fix modifyVendorAttribute not applied (#62) - Fix unncessary status-server when in minimal mode (#61) 2019-10-01 1.8.1 Bug fixes: - Handle Tunnel-Password attribute correctly - Fix BSD platform issues - Fix spelling in log messages and manpages - Fix compile issues for unit tests - Don't hardcode location of config files 2019-07-04 1.8.0 New features: - Rewrite: supplement attribute (add attribute if not present) (#19) - Rewrite: modify vendor attribute - Rewrite whitelist mode - Autodetect status-server capability of servers - Minimalistic status-server - Explicit SubjectAltName:DNS and :IP match on certificates Misc: - No longer require docbook2x tools, but include plain manpages - Fail on startup if overlapping clients with different tls blocks Compile fixes: - Fix compile issues on bsd Bug fixes: - Handle %00 in config correctly (#31) - Fix server selection when udp were unreachable for long periods 2018-09-03 1.7.2 Misc: - Always copy proxy-state attributes in own responses - Authenticate own access-reject responses - Retry outstanding requests after connection reset Compile fixes: - Fix compile issues on some platforms (#14) - Fix compile issue when dtls disabled (#16) - Fix compile issue on Cygwin (#18) - Fix radsecproxy.conf manpage not installed when docbook2x not available Bug fixes: - Fix request might be dropped if udp client uses multiple source ports - Fix tls output might drop requests under high load - Check for IP literals in Certificate SubjectAltName:DNS records - Fix tls connection might hang during SSL_connect and SSL_accept 2018-07-05 1.7.1 License and copyright changes: - Copyright SWITCH - 3-clause BSD license only, no GPL. Enhancements: - Support the use of OpenSSL version 1.1 and 1.0 series (RADSECPROXY-66, RADSECPROXY-74). - Reload TLS certificate CRLs on SIGHUP (RADSECPROXY-78). - Make use of SO_KEEPALIVE for tcp sockets (RADSECPROXY-12). - Optionally include the thread-id in log messages - Allow hashing MAC addresses in the log (same as for F-Ticks) - Log certificate subject if rejected - Log own responses (RADSECPROXY-61) - Allow f-ticks prefix to be configured - radsecproxy-hash: allow MAC addresses to be passed on command line Misc: - libnettle is now an unconditional dependency. - FTicks support is now on by default and not optional. - Experimental code for dynamic discovery has been removed. - Replace several server status bits with a single state enum. (RADSECPROXY-71) - Use poll instead of select to allow > 1000 concurrent connections. - Implement locking for all SSL objects (openssl states it is not thread-safe) - Rework DTLS code. Bug fixes: - Detect the presence of docbook2x-man correctly. - Make clang less unhappy. - Don't use a smaller pthread stack size than what's allowed. - Avoid a deadlock situation with dynamic servers (RADSECPROXY-73). - Don't forget about good dynamically discovered (TLS) connections (RADSECPROXY-69). - Fix refcounting in error cases when loading configuration (RADSECPROXY-42) - Fix potential crash when rewriting malformed vendor attributes. - Properly cleanup expired requests from server output-queue. - Fix crash when dynamic discovered server doesn't resolve. 2017-08-02 1.6.9 Misc: - Use a listen(2) backlog of 128 (RADSECPROXY-72). Bug fixes: - Don't follow NULL the pointer at debug level 5 (RADSECPROXY-68). - Completely reload CAs and CRLs with cacheExpiry (RADSECPROXY-50). - Tie Access-Request log lines to response log lines (RADSECPROXY-60). - Fix a couple of memory leaks and NULL ptr derefs in error cases. - Take lock on realm refcount before updating it (RADSECPROXY-77). 2016-09-21 1.6.8 Bug fixes: - Stop waiting on writable when reading a TCP socket. - Stomp less on the memory of other threads (RADSECPROXY-64). 2016-03-14 1.6.7 Enhancements (security): - Negotiate TLS1.1, TLS1.2 and DTLS1.2 when possible, client and server side. Fixes RADSECPROXY-62. Enhancements: - Build HTML documentation properly. 2015-01-19 1.6.6 Bug fixes (security): - Fix two use-after-free, a null pointer dereference and three heap overflows. Patches by Stephen Röttger. Bug fixes: - Have rewriteIn for servers use the correct config section. We used to apply rewriteIn using the rewrite block of the client rather than the server. Patch by Fabian Mauchle. Fixes RADSECPROXY-59. - Handle CHAP authentication properly when there is no CHAP-Challenge. Fixes RADSECPROXY-58. - Install radsecproxy.conf.5 unconditionally. Keep regeneration of it dependent on configure finding docbook2x-man(1). 2013-09-06 1.6.5 Bug fixes: - Fix a crash bug introduced in 1.6.4. Fixes RADSECPROXY-53, bugfix on 1.6.4. 2013-09-05 1.6.4 Bug fixes: - Keeping Proxy-State attributes in all replies to clients (RADSECPROXY-52). Reported by Stefan Winter. 2013-09-05 1.6.3 Enhancements: - Threads are allocated with a 32 KB stack rather than what happens to be the default. Patch by Fabian Mauchle. - On systems with mallopt(3), freed memory is returned to the system more aggressively. Patch by Fabian Mauchle. Bug fixes: - radsecproxy-hash(1) no longer prints the hash four times. Reported by Simon Lundström and jocar. - Escaped slashes in regular expressions now works. Reported by Duarte Fonseca. (RADSECPROXY-51) - The duplication cache is purged properly. Patch by Fabian Mauchle. - Stop freeing a shared piece of memory manifesting itself as a crash when using dynamic discovery. Patch by Fabian Mauchle. - Closing and freeing TLS clients properly. Patch by Fabian Mauchle. - Timing out on TLS clients not closing the connection properly. Patch by Fabian Mauchle. 2012-10-25 1.6.2 Bug fixes (security): - Fix the issue with verification of clients when using multiple 'tls' config blocks (RADSECPROXY-43) for DTLS too. Fixes CVE-2012-4566 (CVE id corrected 2012-11-01, after the release of 1.6.2). Reported by Raphael Geissert. 2012-09-14 1.6.1 Bug fixes (security): - When verifying clients, don't consider config blocks with CA settings ('tls') which differ from the one used for verifying the certificate chain. Reported by Ralf Paffrath. (RADSECPROXY-43, CVE-2012-4523). Bug fixes: - Make naptr-eduroam.sh check NAPTR type case insensitively. Fix from Adam Osuchowski. 2012-04-27 1.6 Incompatible changes: - The default shared secret for TLS and DTLS connections change from "mysecret" to "radsec" as per draft-ietf-radext-radsec-12 section 2.3 (4). Please make sure to specify a secret in both client and server blocks to avoid unwanted surprises. (RADSECPROXY-19) - The default place to look for a configuration file has changed from /etc to /usr/local/etc. Let radsecproxy know where your configuration file can be found by using the `-c' command line option. Or configure radsecproxy with --sysconfdir=/etc to restore the old behaviour. (RADSECPROXY-31) New features: - Improved F-Ticks logging options. F-Ticks can now be sent to a separate syslog facility and the VISINST label can now be configured explicitly. This was implemented by Maja Gorecka-Wolniewicz and PaweÅ‚ GoÅ‚aszewski. (RADSECPROXY-29) - New config option PidFile. (RADSECPROXY-32) - Preliminary support for DynamicLookupCommand added. It's for TLS servers only at this point. Also, beware of risks for memory leaks. In addition to this, for extra adventurous users, there's a new configure option --enable-experimental-dyndisc which enables even more new code for handling of dynamic discovery of TLS servers. - Address family (IPv4 or IPv6) can now be specified for clients and servers. (RADSECPROXY-37) Bug fixes: - Stop the autoconfery from warning about defining variables conditionally and unconditionally. - Honour configure option --sysconfdir. (RADSECPROXY-31) - Don't crash on failing DynamicLookupCommand scripts. Fix made with help from Ralf Paffrath. (RADSECPROXY-33) - When a DynamicLookupCommand script is failing, fall back to other server(s) in the realm. The timeout depends on the kind of failure. - Other bugs. (RADSECPROXY-26, -28, -34, -35, -39, -40) 2011-10-08 1.5 New features: - Support for F-Ticks logging. - New binary radsecproxy-hash. - A DynamicLookupCommand script can now signal "server not found" by exiting with code 10. The scripts in the tools directory now do this. Incompatible changes: - catgconf renamed to radsecproxy-conf. Bug fixes: - All compiler warnings removed. Now compiling with -Werror. 2011-07-22 1.4.3 Notes: - The default secret for TLS and DTLS will change in a future release. Please make sure to specify a secret in both client and server blocks to avoid surprises. Bug fixes: - Debug printout issue. 2010-11-23 1.4.2 Bug fixes: - Don't disable OpenSSL session caching for 0.9.8p and newer in the 0.9.x track. - Detect OpenSSL version at runtime rather than at compile time. 2010-11-17 1.4.1 Bug fixes: - OpenSSL session caching is disabled when built against OpenSSL older than 1.0.0b to mitigate possible effects of http://openssl.org/news/secadv_20101116.txt (RADSECPROXY-14). - Crash bug when reading improper config file fixed. 2010-06-12 1.4 Incompatible changes: - Log level 4 used to be DBG_DBG but is now DBG_NOTICE. In order to keep the same behaviour as in previous versions of radsecproxy, those who have LogLevel set to 4 need to change this to 5. Log levels 1, 2 and 3 are unaffected. New features and various improvements: - LoopPrevention per server has been added. - AddVendorAttribute rewrite configuration has been added. - New log level, DBG_NOTICE, added. - Diagnostics improved for errors resulting from failing syscalls. - Removed all compiler warnings (compiling with -Wall). Bug fixes: - A UDP fragmentation issue. - Build on Solaris when compiling with gcc. - A bug in pwdencrypt() with passwords of a length greater than 16 octets. 2009-07-22 1.3.1 Fixed header files for FreeBSD Fix for multiple UDP servers on same IP address, solves accounting problems. 2009-03-12 1.3 Fixed some very minor bugs Changed log levels for some messages, made loglevel 2 default 2009-02-18 1.3-beta Client and Server blocks may contain multiple host options. Configure (Makefile) options for specifying which transports should be supported in a build. 2008-12-04 1.3-alpha Support for TCP and DTLS transports (type tcp, type dtls) Listen... options can be specified multiple times Dynamic server discovery DuplicateInterval option in client block for specifying for how long a request/reply shall be stored for duplicate detection Support for RADIUS TTL (hopcount) attribute. Decrements value of the TTL attribute if present, discards message if becomes 0. If addTTL option is used, the TTL attribute is added with the specified value if the forwarded message does not have one. PolicyOID option can be used to require certain CA policies. 2008-10-07 1.2 listenTCP and sourceTCP options renamed to listenTLS and sourceTLS Old options deprecated but available for backwards compatibility Logging reply-message attribute from Reject messages Contribution from Arne Schwabe Rewrite blocks have new options addAttribute and modifyAttribute rewriteIn (replacing rewrite) and rewriteOut in client and server blocks for specifying rewrite on input/output. rewrite deprecated but available as an alias for rewriteIn for backwards compatibility. rewritein rewriteout rewrite regular expressions in realms etc can now be more advanced, including use of "or". cacheExpiry option in tls blocks for specifying expiry time for the cache of CA certificates and CRLs. This is particularly useful for regularly updating CRLs. Some logging has been made more informative 2008-07-24 1.1 Logging stationid attribute Added LoopPrevention option Failover also without status-server Options for RetryCount and RetryInterval Working accounting and AccountingResponse option CRL checking and option for enabling it 2008-05-14 1.1-beta No longer looks for radsecproxy.conf in current directory Rewrite block that allows removal of specified attributes certificateNameCheck option for disabling CN/SubjectAltName check matchCertificateAttribute now also supports CN matching Forwarding of accounting messages, accountingServer option for realms Supports multiple client blocks for same source address with different certificate checks Removed weekday from log timestamps 2007-12-24 1.1-alpha Pretend option for validating configuration Include option for including additional config files Allows clients configured by IP prefix, dynamic clients Server failover support Rewriting of username attribute Source address and port can be specified for requests 2007-10-16 1.0p1 Fixed crash when servers were configured after first realm block 2007-09-21 1.0 radsecproxy-1.11.1/AUTHORS0000644000076600000240000000112714452772710010700 Radsecproxy was written by Stig Venaas. Radsecproxy is currently being maintained by Fabian Mauchle: fabian.mauchle@switch.ch The following people have contributed to Radsecproxy in one way or another: Adam Osuchowski Andreas Solberg Arne Schwabe Christian Hesse Fabian Mauchle Faidon Liambotis Guy Halse Hans Zandbelt Harshit Jain Jan-Frederik Rieckers Jerry Zhao Kolbjørn Barmen Leonhard Knauff Linus Nordberg Luke Benes Maja Wolniewicz Milan Sova Paul Dekkers PaweÅ‚ GoÅ‚aszewski Ralf Paffrath Robert Scheck Simon Leinen Simon Lundström Stefan Winter Stephen Röttger Stig Venaas Sven Hartge radsecproxy-1.11.1/dns.c0000644000076600000240000002415114722543325010560 /* Copyright (c) 2021, SWITCH */ /* See LICENSE for licensing information. */ #include "dns.h" #include "debug.h" #include #include #include #include /** * Read a character string from a dns response * Character strings are represented by a length byte followd by the characters. * * @param dest where to write the string. The provided buffer must be at least 256 bytes in size * @param rdata the rdata pointer from the dns rr * @param offset the offset into rdata where the character string starts * @param rdlen the rlden of the rr, to avoid reading beyond the record * @return the number of bytes read from rdata, or -1 in case of errors */ static uint16_t dnsreadcharstring(char *dest, const u_char *rdata, uint16_t offset, uint16_t rdlen) { uint16_t len; len = *(rdata + offset++); if (offset + len > rdlen) { debug(DBG_ERR, "dnsreadcharstring: error parsing char string, length is beyond radata!"); return -1; } memcpy(dest, rdata + offset, len); *(dest + len) = '\0'; return len + 1; } /** * Parse SRV response. * returns allocated memroy. * * @param msg complete DNS msg structure * @param rr specific SRV resource record in msg * @return new srv_record from resource record */ static void *parsesrvrr(ns_msg msg, ns_rr *rr) { struct srv_record *response; const u_char *rdata; int len; if (ns_rr_type(*rr) != ns_t_srv) return NULL; response = malloc(sizeof(struct srv_record)); if (!response) return NULL; rdata = ns_rr_rdata(*rr); response->ttl = ns_rr_ttl(*rr); response->priority = ns_get16(rdata); response->weight = ns_get16(rdata + 2); response->port = ns_get16(rdata + 4); len = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), rdata + 6, response->host, NS_MAXDNAME); if (len == -1) { debug(DBG_ERR, "parsesrvrr: error during dname uncompress"); free(response); return NULL; } if (strcmp(response->host, ".") == 0) { /* target not available at this domain, as per RFC2782 */ free(response); return NULL; } debug(DBG_DBG, "parsesrvrr: parsed: host %s, port %d, priority %d, weight %d", response->host, response->port, response->priority, response->weight); return response; } /** * Parse NAPTR response. * returns allocated memroy. * * @param msg complete DNS msg structure * @param rr specific SRV resource record in msg * @return new srv_record from resource record */ static void *parsenaptrrr(ns_msg msg, ns_rr *rr) { struct naptr_record *response; const u_char *rdata; uint16_t rdlen, offset = 0; int len; if (ns_rr_type(*rr) != ns_t_naptr) { return NULL; } response = malloc(sizeof(struct naptr_record)); if (!response) return NULL; rdata = ns_rr_rdata(*rr); rdlen = ns_rr_rdlen(*rr); response->ttl = ns_rr_ttl(*rr); response->order = ns_get16(rdata); response->preference = ns_get16(rdata + 2); offset = 4; len = dnsreadcharstring(response->flags, rdata, offset, rdlen); if (len == -1) goto errexit; offset += len; len = dnsreadcharstring(response->services, rdata, offset, rdlen); if (len == -1) goto errexit; offset += len; len = dnsreadcharstring(response->regexp, rdata, offset, rdlen); if (len == -1) goto errexit; offset += len; len = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), rdata + offset, response->replacement, NS_MAXDNAME); if (len == -1) goto errexit; /* sanity check, should be exactly at the end of the rdata */ if (offset + len != rdlen) { debug(DBG_ERR, "parsenaptrrr: sanity check failed! unexpected error while parsing naptr rr"); goto errexit; } debug(DBG_DBG, "parsenaptrrr: parsed: service %s, regexp %s, replace %s, flags %s, order %d, preference %d", response->services, response->regexp, response->replacement, response->flags, response->order, response->preference); return response; errexit: free(response); return NULL; } /* use a packet buffer of 4k insteady of the default 512 byets defined by NS_PACKETSZ */ #define DNS_PACKETSIZE 4096 /** * Internal structure to hold resolver state and buffer */ struct query_state { struct __res_state rs; u_char buf[DNS_PACKETSIZE]; ns_msg msg; }; /** * Cleanup (close) and free a query state * * @param state the query state to close */ static void querycleanup(struct query_state *state) { if (state) { #if __RES >= 19991006 res_nclose(&state->rs); #endif free(state); } } /** * Internal helper to perform a dns query. * Implicitly initializes the resolver * * @param type the DNS type to query * @param name the DNS name to query * @return initilized query state, its buffer containing the response, or NULL in case of error */ static struct query_state *doquery(int type, const char *name, int timeout) { int len; char *errstring; struct query_state *state = malloc(sizeof(struct query_state)); if (!state) { debug(DBG_ERR, "malloc failed"); return NULL; } memset(state, 0, sizeof(struct query_state)); debug(DBG_DBG, "doquery: starting DNS query of type %d for %s", type, name); #if __RES >= 19991006 /* new thread-safe res_n* functions introduced in this version */ if (res_ninit(&state->rs)) { debug(DBG_ERR, "doquery: resolver init failed"); free(state); return NULL; } state->rs.retrans = timeout; state->rs.retry = 1; len = res_nquery(&state->rs, name, ns_c_in, type, state->buf, DNS_PACKETSIZE); if (len == -1) { switch (state->rs.res_h_errno) { #else /* only the old interface is available. We have to trust the system to use a thread-safe implementation */ res_init(); _res.retrans = timeout; _res.retry = 1; len = res_query(name, ns_c_in, type, state->buf, DNS_PACKETSIZE); if (len == -1) { switch (h_errno) { #endif case HOST_NOT_FOUND: errstring = "domain not found"; break; case NO_DATA: errstring = "no records"; break; case NO_RECOVERY: errstring = "format error or refused"; break; case TRY_AGAIN: errstring = "server error"; break; default: errstring = "internal error"; } debug(DBG_NOTICE, "doquery: dns query failed: %s", errstring); querycleanup(state); return NULL; } if (ns_initparse(state->buf, len, &state->msg) == -1) { debug(DBG_ERR, "doquery: dns response parser init failed"); querycleanup(state); return NULL; } /* we should have a valid resopnse at this point, but check the response code anyway, to be sure */ if (ns_msg_getflag(state->msg, ns_f_rcode) != ns_r_noerror) { debug(DBG_ERR, "doquery: dns query returned error code %d", ns_msg_getflag(state->msg, ns_f_rcode)); querycleanup(state); return NULL; } /* TODO option to check for DNSSEC AD (authentic data) flag? */ return state; } /** * Internal helper to find all records of a given type in a section * Each matching record is passed to a parser which should read the record and return an allocated memory * containing its result. * The sum of matching records is returned as a null terminated array of pointers. * * @param state the query state containing the result buffer * @param type the type to search for * @param section the section to serch in * @param parser implementation to turn the raw resrouce record into a usable format. * @return the matching and parseable results */ static void **findrecords(struct query_state *state, int type, int section, void *parser(ns_msg, ns_rr *)) { void **result; void *record; ns_rr rr; int rr_count, i, numresults = 0; debug(DBG_DBG, "findrecords: looking for results of type %d in section %d", type, section); rr_count = ns_msg_count(state->msg, ns_s_an); debug(DBG_DBG, "findrecords: total %d records in section %d", rr_count, section); result = calloc(rr_count + 1, sizeof(void *)); if (!result) { debug(DBG_ERR, "malloc failed"); return NULL; } for (i = 0; i < rr_count; i++) { if (ns_parserr(&state->msg, ns_s_an, i, &rr)) { debug(DBG_ERR, "findrecords: error parsing record %d", i); continue; } if (ns_rr_type(rr) == type) { record = parser(state->msg, &rr); if (!record) { debug(DBG_ERR, "findrecords: error parsing record %d", i); continue; } result[numresults++] = record; } } debug(DBG_DBG, "findrecords: %d records of desired type successfully parsed", numresults); return result; } struct srv_record **querysrv(const char *name, int timeout) { struct srv_record **result; struct query_state *state; state = doquery(ns_t_srv, name, timeout); if (!state) return NULL; result = (struct srv_record **)findrecords(state, ns_t_srv, ns_s_an, &parsesrvrr); /* TODO response could include A and AAAA records for the hosts, add this info to the returned result */ querycleanup(state); return result; } struct naptr_record **querynaptr(const char *name, int timeout) { struct naptr_record **result; struct query_state *state; state = doquery(ns_t_naptr, name, timeout); if (!state) return NULL; result = (struct naptr_record **)findrecords(state, ns_t_naptr, ns_s_an, &parsenaptrrr); querycleanup(state); return result; } /** * Internal generic function to free null terminated lists that contained a response * from calling a query_* function. * * @param list the list to free */ void freeresponselist(void **list) { int i; if (list) { for (i = 0; list[i]; i++) { free(list[i]); } free(list); } } void freesrvresponse(struct srv_record **response) { freeresponselist((void **)response); } void freenaptrresponse(struct naptr_record **response) { freeresponselist((void **)response); } radsecproxy-1.11.1/tests/0000755000076600000240000000000014724611072011044 5radsecproxy-1.11.1/tests/t_rewrite.c0000644000076600000240000006057114722543325013150 /* Copyright (C) 2019, SWITCH */ /* See LICENSE for licensing information. */ #include "../debug.h" #include "../radmsg.h" #include "../rewrite.h" #include #include #include #include static void printescape(uint8_t *v, uint8_t l) { int i; for (i = 0; i < l; i++) { if (isprint(v[i])) printf("%c", v[i]); else printf("\\x%02x", v[i]); } } /*origattrs and expectedattrs as struct tlv*/ /*return 0 if expected; 1 otherwise or error*/ static int _check_rewrite(struct list *origattrs, struct rewrite *rewrite, struct list *expectedattrs, int shouldfail) { struct radmsg msg; struct list_node *n, *m; int i = 1; msg.attrs = origattrs; if (dorewrite(&msg, rewrite) == shouldfail) { if (shouldfail) printf("dorewrite expected to fail, but it didn't\n"); else printf("dorewrite failed\n"); return 1; } if (list_count(expectedattrs) != list_count(msg.attrs)) { printf("bad attribute list length! expected %d, was %d\n", list_count(expectedattrs), list_count(msg.attrs)); return 1; } m = list_first(origattrs); for (n = list_first(expectedattrs); n; n = list_next(n)) { struct tlv *tlv_exp = (struct tlv *)n->data, *tlv_act = (struct tlv *)m->data; if (!eqtlv(tlv_exp, tlv_act)) { printf("attribute list at %d not as expected!\n", i); printf(" expected type: %d, actual type: %d\n", tlv_exp->t, tlv_act->t); printf(" expected length: %d, actual length: %d\n", tlv_exp->l, tlv_act->l); printf(" expected value: "); printescape(tlv_exp->v, tlv_exp->l); printf(" actual value: "); printescape(tlv_act->v, tlv_act->l); printf("\n"); return 1; } m = list_next(m); i++; } return 0; } void _list_clear(struct list *list) { void *data; while ((data = list_shift(list))) free(data); } void _tlv_list_clear(struct list *list) { struct tlv *tlv; while ((tlv = (struct tlv *)list_shift(list))) freetlv(tlv); } void _reset_rewrite(struct rewrite *rewrite) { rewrite->whitelist_mode = 0; rewrite->removeattrs = NULL; rewrite->removevendorattrs = NULL; _tlv_list_clear(rewrite->addattrs); _list_clear(rewrite->modattrs); _list_clear(rewrite->modvattrs); _tlv_list_clear(rewrite->supattrs); } int main(int argc, char *argv[]) { int testcount = 26; struct list *origattrs, *expectedattrs; struct rewrite rewrite; char *username = "user@realm"; debug_init("t_rewrite"); origattrs = list_create(); expectedattrs = list_create(); rewrite.whitelist_mode = 0; rewrite.removeattrs = NULL; rewrite.removevendorattrs = NULL; rewrite.addattrs = list_create(); rewrite.modattrs = list_create(); rewrite.modvattrs = list_create(); rewrite.supattrs = list_create(); printf("1..%d\n", testcount); testcount = 1; /* test empty rewrite */ { list_push(origattrs, maketlv(RAD_Attr_User_Name, strlen(username), username)); list_push(expectedattrs, maketlv(RAD_Attr_User_Name, strlen(username), username)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - empty rewrite\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test removeattr */ { uint8_t removeattrs[] = {1, 2, 0}; rewrite.removeattrs = removeattrs; list_push(origattrs, maketlv(1, strlen(username), username)); list_push(origattrs, maketlv(3, strlen(username), username)); list_push(expectedattrs, maketlv(3, strlen(username), username)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - removeattrs\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test removevendorattrs full: remove a vendor attribute completely*/ { uint32_t removevendorattrs[] = {42, 256, 0}; uint8_t value = 42; rewrite.removevendorattrs = removevendorattrs; list_push(origattrs, maketlv(1, strlen(username), username)); list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); list_push(expectedattrs, maketlv(1, strlen(username), username)); list_push(expectedattrs, makevendortlv(43, maketlv(1, 1, &value))); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - removevendorattrs full\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test removevendorattrs last element: remove vendor attribute if last subattribute removed*/ { uint32_t removevendorattrs[] = {42, 2, 0}; /*,45,12}; remove vendor 42, type 2; vendor 43 all, vendor 45 type 12} */ uint8_t value = 42; rewrite.removevendorattrs = removevendorattrs; list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(42, maketlv(2, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(2, 1, &value))); list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(expectedattrs, makevendortlv(43, maketlv(2, 1, &value))); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - removevendorattrs last element\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test removevendorattrs non-rfc: dont remove if format doesn't follow rfc recommendation*/ { uint32_t removevendorattrs[] = {42, 1, 0}; uint8_t vendor_nonrfc[] = {0, 0, 0, 45, 1, 0x12, 0x23}; rewrite.removevendorattrs = removevendorattrs; list_push(origattrs, maketlv(26, 7, vendor_nonrfc)); list_push(expectedattrs, maketlv(26, 7, vendor_nonrfc)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - removevendorattrs non-rfc\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test removevendorattrs partial attribute */ { uint32_t removevendorattrs[] = {42, 2, 0}; uint8_t vendor_long1_in[] = {0, 0, 0, 42, 2, 3, 0, 1, 3, 0}; uint8_t vendor_long1_out[] = {0, 0, 0, 42, 1, 3, 0}; uint8_t vendor_long2_in[] = {0, 0, 0, 42, 1, 3, 0, 2, 3, 0}; uint8_t vendor_long2_out[] = {0, 0, 0, 42, 1, 3, 0}; uint8_t vendor_long3_in[] = {0, 0, 0, 42, 1, 3, 0, 2, 3, 0, 3, 3, 0}; uint8_t vendor_long3_out[] = {0, 0, 0, 42, 1, 3, 0, 3, 3, 0}; rewrite.removevendorattrs = removevendorattrs; list_push(origattrs, maketlv(26, sizeof(vendor_long1_in), vendor_long1_in)); list_push(origattrs, maketlv(26, sizeof(vendor_long2_in), vendor_long2_in)); list_push(origattrs, maketlv(26, sizeof(vendor_long3_in), vendor_long3_in)); list_push(expectedattrs, maketlv(26, sizeof(vendor_long1_out), vendor_long1_out)); list_push(expectedattrs, maketlv(26, sizeof(vendor_long2_out), vendor_long2_out)); list_push(expectedattrs, maketlv(26, sizeof(vendor_long3_out), vendor_long3_out)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - removevendorattrs sub-attribute\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test simple add */ { char *value = "hello world"; list_push(rewrite.addattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - addattribute simple\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test add with existing attributes*/ { char *value = "hello world"; uint8_t value2 = 42; list_push(rewrite.addattrs, maketlv(1, strlen(value), value)); list_push(origattrs, maketlv(2, strlen(value), value)); list_push(origattrs, maketlv(1, 1, &value2)); list_push(expectedattrs, maketlv(2, strlen(value), value)); list_push(expectedattrs, maketlv(1, 1, &value2)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - addattribute with existing attributes\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test add null*/ { list_push(rewrite.addattrs, maketlv(1, 0, NULL)); list_push(expectedattrs, maketlv(1, 0, NULL)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - addattribute null\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test add too big*/ { uint8_t *value = malloc(254); memset(value, 0, 254); list_push(rewrite.addattrs, maketlv(1, 254, value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 1)) printf("not "); printf("ok %d - addattribute too big\n", testcount++); free(value); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test supplement non-existing*/ { char *value = "hello world"; list_push(rewrite.supattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - suppattrs non existing\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test supplement existing*/ { char *value = "hello world"; char *value2 = "hello radsec"; list_push(rewrite.supattrs, maketlv(1, strlen(value2), value2)); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - suppattrs existing\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test supplement vendor*/ { uint8_t value = 42; uint8_t vendor_long1_in[] = {0, 0, 0, 42, 2, 3, 0, 1, 3, 0}; list_push(rewrite.supattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(rewrite.supattrs, makevendortlv(42, maketlv(3, 1, &value))); list_push(origattrs, maketlv(26, sizeof(vendor_long1_in), vendor_long1_in)); list_push(expectedattrs, maketlv(26, sizeof(vendor_long1_in), vendor_long1_in)); list_push(expectedattrs, makevendortlv(42, maketlv(3, 1, &value))); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - suppattrs vendor\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify no match*/ { char *value = "hello world"; char *value2 = "foo bar"; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 1; mod->regex = ®ex; mod->replacement = value2; regcomp(mod->regex, "hello bar", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify attribute no match\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify match full replace*/ { char *value = "hello world"; char *value2 = "foo bar"; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 1; mod->regex = ®ex; mod->replacement = value2; regcomp(mod->regex, "hello world", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value2), value2)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify attribute match full replace\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify match partial replace*/ { char *value = "hello world"; char *value2 = "hello foo"; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 1; mod->regex = ®ex; mod->replacement = "\\1 foo"; regcomp(mod->regex, "(hello) world", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value2), value2)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify attribute match full replace\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify max length*/ { char *value = "hello radsecproxy..."; /*make this 20 chars long 8*/ char value2[254]; int i; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; for (i = 0; i < 253 - 20; i += 20) { memcpy(value2 + i, value, 20); } memcpy(value2 + i, "and another13\0", 14); mod->t = 1; mod->regex = ®ex; mod->replacement = "\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1and another13"; regcomp(mod->regex, "(.*)", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value2), value2)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify attribute max length\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify too long*/ { char *value = "hello radsecproxy..."; /*make this 20 chars long 8*/ struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 1; mod->regex = ®ex; mod->replacement = "\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1and another14!"; regcomp(mod->regex, "(.*)", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value), value)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 1)) printf("not "); printf("ok %d - modify attribute too long\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify regex replace*/ { char *value = "hello"; char *value2 = "hellohellohellohellohellohellohellohellohello"; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 1; mod->regex = ®ex; mod->replacement = "\\1\\2\\3\\4\\5\\6\\7\\8\\9"; regcomp(mod->regex, "(((((((((hello)))))))))", REG_ICASE | REG_EXTENDED); list_push(rewrite.modattrs, mod); list_push(origattrs, maketlv(1, strlen(value), value)); list_push(expectedattrs, maketlv(1, strlen(value2), value2)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify attribute regex replace\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify vendor*/ { struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; uint8_t vendorattrin[] = {0, 0, 0, 42, 1, 3, 'b', 1, 3, 'a', 2, 3, 0, 1, 3, 'a'}; uint8_t vendorattrout[] = {0, 0, 0, 42, 1, 3, 'b', 1, 4, 'b', 'b', 2, 3, 0, 1, 4, 'b', 'b'}; mod->t = 1; mod->vendor = 42; mod->regex = ®ex; mod->replacement = "bb"; regcomp(mod->regex, "a", REG_ICASE | REG_EXTENDED); list_push(rewrite.modvattrs, mod); list_push(origattrs, maketlv(RAD_Attr_Vendor_Specific, sizeof(vendorattrin), vendorattrin)); list_push(expectedattrs, maketlv(RAD_Attr_Vendor_Specific, sizeof(vendorattrout), vendorattrout)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - modify vendor\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test modify vendor too long (total vendor attribute too long) */ { struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; uint8_t vendorattrin[RAD_Max_Attr_Value_Length]; memset(vendorattrin, 0, RAD_Max_Attr_Value_Length); vendorattrin[3] = 42; vendorattrin[4] = 1; vendorattrin[5] = 3; vendorattrin[6] = 'a'; vendorattrin[7] = 2; vendorattrin[8] = RAD_Max_Attr_Value_Length - 7; mod->t = 1; mod->vendor = 42; mod->regex = ®ex; mod->replacement = "bb"; regcomp(mod->regex, "a", REG_ICASE | REG_EXTENDED); list_push(rewrite.modvattrs, mod); list_push(origattrs, maketlv(RAD_Attr_Vendor_Specific, sizeof(vendorattrin), vendorattrin)); if (_check_rewrite(origattrs, &rewrite, origattrs, 1)) printf("not "); printf("ok %d - modify vendor too long\n", testcount++); regfree(®ex); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test whitelist rewrite */ { uint8_t whitelistattrs[] = {1, 0}; rewrite.whitelist_mode = 1; rewrite.removeattrs = whitelistattrs; list_push(origattrs, maketlv(1, strlen(username), username)); list_push(origattrs, maketlv(3, strlen(username), username)); list_push(origattrs, makevendortlv(42, maketlv(1, strlen(username), username))); list_push(expectedattrs, maketlv(1, strlen(username), username)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - whitelistattrs\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test whitelist vendor rewrite */ { uint32_t whitelistvendorattrs[] = {42, 256, 0}; uint8_t value = 42; uint8_t vendor_nonrfc_in[] = {0, 0, 0, 42, 1, 2, 3, 4}; rewrite.whitelist_mode = 1; rewrite.removevendorattrs = whitelistvendorattrs; list_push(origattrs, maketlv(1, strlen(username), username)); list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); list_push(origattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(expectedattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - whitelistvendorattrs\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test whitelist vendor rewrite subattribute*/ { uint32_t whitelistvendorattrs[] = {42, 1, 0}; uint8_t value = 42; uint8_t vendor_long1_in[] = {0, 0, 0, 42, 2, 3, 0, 1, 3, 0}; uint8_t vendor_long1_out[] = {0, 0, 0, 42, 1, 3, 0}; uint8_t vendor_nonrfc_in[] = {0, 0, 0, 42, 1, 2, 3, 4}; rewrite.whitelist_mode = 1; rewrite.removevendorattrs = whitelistvendorattrs; list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(42, maketlv(2, 1, &value))); list_push(origattrs, maketlv(26, sizeof(vendor_long1_in), vendor_long1_in)); list_push(origattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(expectedattrs, maketlv(26, sizeof(vendor_long1_out), vendor_long1_out)); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - whitelistvendorattrs\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test whitelist vendor rewrite combined*/ { uint32_t whitelistvendorattrs[] = {42, 1, 0}; uint8_t whitelistattrs[] = {1, 0}; uint8_t value = 42; rewrite.whitelist_mode = 1; rewrite.removeattrs = whitelistattrs; rewrite.removevendorattrs = whitelistvendorattrs; list_push(origattrs, maketlv(1, strlen(username), username)); list_push(origattrs, maketlv(3, strlen(username), username)); list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); list_push(origattrs, makevendortlv(43, maketlv(2, 1, &value))); list_push(expectedattrs, maketlv(1, strlen(username), username)); list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - whitelistvendorattrs\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } /* test issue #62 rewrite 9:102:/^(h323-credit-time).*$/\1=86400/ */ { char *value = "h323-credit-time=1846422"; char *expect = "h323-credit-time=86400"; struct modattr *mod = malloc(sizeof(struct modattr)); regex_t regex; mod->t = 102; mod->vendor = 9; mod->regex = ®ex; mod->replacement = "\\1=86400"; regcomp(mod->regex, "^(h323-credit-time).*$", REG_ICASE | REG_EXTENDED); list_push(rewrite.modvattrs, mod); list_push(origattrs, makevendortlv(9, maketlv(102, strlen(value), value))); list_push(expectedattrs, makevendortlv(9, maketlv(102, strlen(expect), expect))); if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) printf("not "); printf("ok %d - issue #62\n", testcount++); _tlv_list_clear(origattrs); _tlv_list_clear(expectedattrs); _reset_rewrite(&rewrite); } list_destroy(origattrs); list_destroy(expectedattrs); list_destroy(rewrite.addattrs); list_destroy(rewrite.modattrs); list_destroy(rewrite.modvattrs); list_destroy(rewrite.supattrs); return 0; } radsecproxy-1.11.1/tests/t_unhex.c0000644000076600000240000001751014722543325012611 /* Copyright (C) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "../gconfig.h" #include "../util.h" #include #include #include #include static void printhex(uint8_t *str, size_t len) { int i = 0; for (; i < len; i++) { printf("%02x", str[i]); } } static int _check_unhex(char *input, uint8_t process_null, uint8_t *expected, size_t expected_len) { int result = 1; int length = 0; char *str = stringcopy(input, 0); if (strlen(input) < expected_len) { printf("unhex error: expected length can't longer than input length\n"); return 0; } length = unhex(str, process_null); if (length != expected_len) { printf("unhex: expected length %zu, was %d\n", expected_len, length); result = 0; } if (memcmp(str, expected, expected_len) != 0) { result = 0; printf("unhex: expected string "); printhex(expected, expected_len); printf(", was "); printhex((uint8_t *)str, expected_len); printf("\n"); } free(str); return result; } int main(int argc, char *argv[]) { int testcount = 0; { char *input = "test"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - simple test with no hex\n", ++testcount); } { char *input = "test%01"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x01}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - simple hex\n", ++testcount); } { char *input = "test%01t"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x01, 0x74}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - simple hex with following char\n", ++testcount); } { char *input = "test%01%02"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x01, 0x02}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - two hex\n", ++testcount); } { char *input = "test%01%02t"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x01, 0x02, 0x74}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - two hex with flollowing char\n", ++testcount); } { char *input = "test%01t%02t"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x01, 0x74, 0x02, 0x74}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - two hex with flollowing char\n", ++testcount); } { char *input = "test%xy"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x25, 0x78, 0x79}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - not hex\n", ++testcount); } { char *input = "test%0g"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x25, 0x30, 0x67}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - not hex 2\n", ++testcount); } { char *input = "test%0"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x25, 0x30}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - too short\n", ++testcount); } { char *input = "test%xy"; uint8_t expect[] = {0x74, 0x65, 0x73, 0x74, 0x25, 0x78, 0x79}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - not hex\n", ++testcount); } { char *input = "%01"; uint8_t expect[] = {0x01}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - start hex\n", ++testcount); } { char *input = "%01a"; uint8_t expect[] = {0x01, 0x61}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - start hex with following char\n", ++testcount); } { char *input = "%00"; uint8_t expect[] = {0x25, 0x30, 0x30}; if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - skip zero\n", ++testcount); } { char *input = "%00"; uint8_t expect[] = {0x00}; if (!_check_unhex(input, 1, expect, sizeof(expect))) printf("not "); printf("ok %d - convert zero\n", ++testcount); } { char *input = "%"; uint8_t expect[] = {0x25}; if (!_check_unhex(input, 1, expect, sizeof(expect))) printf("not "); printf("ok %d - hex zero length\n", ++testcount); } { char *input = "%%"; uint8_t expect[] = {0x00}; //actually zero length if (!_check_unhex(input, 0, expect, 0)) printf("not "); printf("ok %d - hexstring zero length\n", ++testcount); } { char *input = "%%01"; uint8_t expect[] = {0x01}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring length one\n", ++testcount); } { char *input = "%%0102"; uint8_t expect[] = {0x01, 0x02}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring length two\n", ++testcount); } { char *input = "%%0102030405060708090a0b0c0d0e0f10"; uint8_t expect[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring long\n", ++testcount); } { char *input = "te%%0102st"; uint8_t expect[] = {0x74, 0x65, 0x01, 0x02, 0x73, 0x74}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring leader and trailer\n", ++testcount); } { char *input = "%%01x"; uint8_t expect[] = {0x01, 0x78}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring terminate\n", ++testcount); } { char *input = "%%01ax"; uint8_t expect[] = {0x01, 0x61, 0x78}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring terminate\n", ++testcount); } { char *input = "%%01x%%01"; uint8_t expect[] = {0x01, 0x78, 0x01}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring two strings\n", ++testcount); } { char *input = "%%01%%01"; uint8_t expect[] = {0x01, 0x01}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring two strings no ascii\n", ++testcount); } { char *input = "%%0000"; uint8_t expect[] = {0x00, 0x00}; //actually zero length if (!_check_unhex(input, 1, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring zeroes\n", ++testcount); } { char *input = "%%01%01"; uint8_t expect[] = {0x01, 0x01}; //actually zero length if (!_check_unhex(input, 0, expect, sizeof(expect))) printf("not "); printf("ok %d - hexstring and hexchar mixed\n", ++testcount); } printf("1..%d\n", testcount); return 0; } radsecproxy-1.11.1/tests/t_radmsg.c0000644000076600000240000000222114722543325012730 /* Copyright (C) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "../radmsg.h" #include #include #include #include int numtests = 0; void test_radlen(uint8_t *buf, int expected, char *msg) { int actual = get_checked_rad_length(buf); if (actual != expected) printf("not "); printf("ok %d - radlen %s (expected %d, got %d)\n", ++numtests, msg, expected, actual); } int main(int argc, char *argv[]) { { uint8_t buf[] = {0x0c, 0x00, 0x00, 0x2a}; test_radlen(buf, 42, "basic length test"); } { uint8_t buf[] = {0x0c, 0x00, 0x00, 0x14}; test_radlen(buf, 20, "lower bound"); } { uint8_t buf[] = {0x0c, 0x00, 0x10, 0x00}; test_radlen(buf, 4096, "upper bound"); } { uint8_t buf[] = {0x0c, 0x00, 0x00, 0x13}; test_radlen(buf, -19, "too small"); } { uint8_t buf[] = {0x0c, 0x00, 0x10, 0x01}; test_radlen(buf, -4097, "too big"); } { uint8_t buf[] = {0x0c, 0x00, 0x00, 0x00}; test_radlen(buf, 0, "zero"); } printf("1..%d\n", numtests); } radsecproxy-1.11.1/tests/Makefile.am0000644000076600000240000000102014722543325013014 AUTOMAKE_OPTIONS = foreign #LOG_DRIVER = ./tap-driver.sh LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ $(top_srcdir)/build-aux/tap-driver.sh check_PROGRAMS = \ t_fticks \ t_rewrite \ t_resizeattr \ t_rewrite_config \ t_verify_cert \ t_radmsg \ t_unhex \ t_utf8 \ t_verify_eap AM_CFLAGS = -g -Wall -Werror @OPENSSL_INCLUDES@ @TARGET_CFLAGS@ LDADD = $(top_builddir)/librsp.a @OPENSSL_LIBS@ LDFLAGS = @OPENSSL_LDFLAGS@ @TARGET_LDFLAGS@ @LDFLAGS@ TESTS = $(check_PROGRAMS) radsecproxy-1.11.1/tests/t_verify_eap.c0000644000076600000240000000634014722543325013612 /* Copyright (C) 2024, SWITCH */ /* See LICENSE for licensing information. */ #include "../debug.h" #include "../radmsg.h" #include #include #include #include static int _check_eap(uint8_t *eap, size_t eap_len, int expected) { struct radmsg *msg = radmsg_init(RAD_Access_Request, 0, NULL); int result; while (eap_len > 0) { size_t len = eap_len > 253 ? 253 : eap_len; radmsg_add(msg, maketlv(RAD_Attr_EAP_Message, len, eap), 0); eap += len; eap_len -= len; } result = verifyeapformat(msg); radmsg_free(msg); return result == expected; } static void _set_eap_length(uint8_t *eap, size_t len) { uint16_t eap_len = htons(len); memcpy(eap + 2, &eap_len, sizeof(eap_len)); } int main(int argc, char *argv[]) { int testcount = 0; debug_init("t_verify_eap"); debug_set_level(5); { uint8_t eap[6]; _set_eap_length(eap, sizeof(eap)); if (!_check_eap(eap, sizeof(eap), 1)) printf("not "); printf("ok %d - simple eap\n", ++testcount); } { uint8_t eap[4]; _set_eap_length(eap, sizeof(eap)); if (!_check_eap(eap, sizeof(eap), 1)) printf("not "); printf("ok %d - minimum length\n", ++testcount); } { uint8_t eap[3]; if (!_check_eap(eap, sizeof(eap), 0)) printf("not "); printf("ok %d - too short\n", ++testcount); } { uint8_t eap[253]; _set_eap_length(eap, sizeof(eap)); if (!_check_eap(eap, sizeof(eap), 1)) printf("not "); printf("ok %d - maxxed out attribute\n", ++testcount); } { uint8_t eap[254]; _set_eap_length(eap, sizeof(eap)); if (!_check_eap(eap, sizeof(eap), 1)) printf("not "); printf("ok %d - mimimum overflow\n", ++testcount); } { uint8_t eap[10]; _set_eap_length(eap, 0); if (!_check_eap(eap, sizeof(eap), 0)) printf("not "); printf("ok %d - eap length too short (all zero)\n", ++testcount); } { uint8_t eap[1024]; _set_eap_length(eap, 0); if (!_check_eap(eap, sizeof(eap), 0)) printf("not "); printf("ok %d - eap length too short - very long eap\n", ++testcount); } { uint8_t eap[10]; _set_eap_length(eap, 255); if (!_check_eap(eap, sizeof(eap), 0)) printf("not "); printf("ok %d - eap length too big\n", ++testcount); } { uint8_t eap[1024]; _set_eap_length(eap, 256); if (!_check_eap(eap, sizeof(eap), 0)) printf("not "); printf("ok %d - eap length too big - very long eap\n", ++testcount); } { uint8_t eap[253]; _set_eap_length(eap, sizeof(eap)); struct radmsg *msg = radmsg_init(RAD_Access_Request, 0, NULL); radmsg_add(msg, maketlv(RAD_Attr_EAP_Message, sizeof(eap), eap), 0); radmsg_add(msg, maketlv(RAD_Attr_EAP_Message, 0, eap), 0); if (verifyeapformat(msg) != 0) printf("not "); printf("ok %d - zero length second attribute\n", ++testcount); } printf("1..%d\n", testcount); return 0; } radsecproxy-1.11.1/tests/t_resizeattr.c0000644000076600000240000000267314722543325013662 /* Copyright (C) 2019, SWITCH */ /* See LICENSE for licensing information. */ #include "../rewrite.h" #include #include #include int test_resize(int start_size, int target_size, uint8_t shouldfail) { uint8_t *value = malloc(start_size); struct tlv *attr; int result = 1; memset(value, 42, start_size); attr = maketlv(1, start_size, value); if (!resizeattr(attr, target_size)) result = shouldfail; else if (shouldfail) result = 0; else if (attr->l != target_size) result = 0; else if (memcmp(attr->v, value, target_size <= start_size ? target_size : start_size)) result = 0; freetlv(attr); free(value); return result; } int main(int argc, char *argv[]) { int testcount = 4; printf("1..%d\n", testcount); testcount = 1; /* test resizeattr normal */ if (!test_resize(4, 8, 0)) printf("not "); printf("ok %d - resizeattr\n", testcount++); /* test resizeattr to 0 */ if (!test_resize(4, 0, 0)) printf("not "); printf("ok %d - resizeattr to zero\n", testcount++); /* test resizeattr to max size */ if (!test_resize(128, 253, 0)) printf("not "); printf("ok %d - resizeattr to max size\n", testcount++); /* test resizeattr to oversize */ if (!test_resize(128, 254, 1)) printf("not "); printf("ok %d - resizeattr to oversize\n", testcount++); return 0; } radsecproxy-1.11.1/tests/t_fticks.c0000644000076600000240000000403314722543325012741 /* Copyright (C) 2011,2013, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "../fticks_hashmac.h" #include "../radsecproxy.h" #include #include #include static int _check_hash(const char *mac, const char *key, const char *hash, const char *hmac) { int rv = 0; uint8_t buf[64 + 1]; if (fticks_hashmac((const uint8_t *)mac, NULL, sizeof(buf), buf) != 0) return -ENOMEM; if (strcmp(hash, (const char *)buf) != 0) rv = !!fprintf(stderr, "%s: bad hash: %s\n", mac, buf); if (fticks_hashmac((const uint8_t *)mac, (const uint8_t *)key, sizeof(buf), buf) != 0) return -ENOMEM; if (strcmp(hmac, (const char *)buf) != 0) rv = !!fprintf(stderr, "%s: bad hash (key=\"%s\"): %s\n", mac, key, buf); return rv; } #define MAC1 "00:23:14:0a:f7:24" #define MAC1_UC "00:23:14:0A:F7:24" #define MAC1_APPENDED "00:23:14:0a:f7:24;cruft" #define MAC1_WEIRD "00:23:-[?xyzzy!]-14:0a:f7:24" #define KEY1 "magic passphrase" #define HASH1 "29c0ee9d9c41771795a11ff75fefe9f5ccaab523ad31fc4fd8e776c707ad1581" #define HMAC1 "57c8cd8031142c51ac9747370f48a5aa731006729d0cdf589ba101864f35f390" int main(int argc, char *argv[]) { int testcount = 5; printf("1..%d\n", testcount); testcount = 1; if (_check_hash(MAC1, KEY1, HASH1, HMAC1) != 0) printf("not "); printf("ok %d - basic hash\n", testcount++); /* Again, for good measure. (Or rather to make sure there's no state left.) */ if (_check_hash(MAC1, KEY1, HASH1, HMAC1) != 0) printf("not "); printf("ok %d - hash stateless\n", testcount++); if (_check_hash(MAC1_UC, KEY1, HASH1, HMAC1) != 0) printf("not "); printf("ok %d - hash uppercase\n", testcount++); if (_check_hash(MAC1_APPENDED, KEY1, HASH1, HMAC1) != 0) printf("not "); printf("ok %d - hash appended\n", testcount++); if (_check_hash(MAC1_WEIRD, KEY1, HASH1, HMAC1) != 0) printf("not "); printf("ok %d - hash weird\n", testcount++); return 0; } radsecproxy-1.11.1/tests/t_verify_cert.c0000644000076600000240000005467014722543325014013 /* Copyright (C) 2020, SWITCH */ /* See LICENSE for licensing information. */ #include "../debug.h" #include "../hostport.h" #include "../radsecproxy.h" #include "../util.h" #include #include #include #include X509 *getcert(char *pem) { X509 *certX509; BIO *certBio; certBio = BIO_new(BIO_s_mem()); BIO_write(certBio, pem, strlen(pem)); certX509 = PEM_read_bio_X509(certBio, NULL, NULL, NULL); BIO_free(certBio); return certX509; } int numtests = 0; void ok(int expect, int result, char *descr) { if (result == expect) { printf("ok %d - %s\n", ++numtests, descr); } else { printf("not ok %d - %s\n", ++numtests, descr); } } int main(int argc, char *argv[]) { struct clsrvconf conf; /* /CN=test */ X509 *certsimple = getcert("-----BEGIN CERTIFICATE-----\n\ MIHAMIGMAgkAx2VNeC1d5FswCQYHKoZIzj0EATAPMQ0wCwYDVQQDDAR0ZXN0MB4X\n\ DTIwMDkyODE0MTEzMloXDTIwMTAwODE0MTEzMlowDzENMAsGA1UEAwwEdGVzdDAy\n\ MBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQMNcK0IZozUpupFkD/dWBC37qI\n\ QW4wCQYHKoZIzj0EAQMkADAhAg8Ajl0dHSkadggaqZiD72ACDjWHqYhaIAWTstBv\n\ g/Q5\n\ -----END CERTIFICATE-----"); /* /CN=other */ X509 *certsimpleother = getcert("-----BEGIN CERTIFICATE-----\n\ MIHDMIGOAgkAwf1w/+YshIwwCQYHKoZIzj0EATAQMQ4wDAYDVQQDDAVvdGhlcjAe\n\ Fw0yMDA5MjkwNTE1MjlaFw0yMDEwMDkwNTE1MjlaMBAxDjAMBgNVBAMMBW90aGVy\n\ MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAEnGezNfbihAw1wrQhmjNSm6kWQP91YELf\n\ uohBbjAJBgcqhkjOPQQBAyUAMCICDwDD9T+qjNHU461al3c11gIPAMZbk5wkhd6C\n\ ybOsj/PY\n\ -----END CERTIFICATE-----"); /* /CN=test, SAN DNS:test.local */ X509 *certsandns = getcert("-----BEGIN CERTIFICATE-----\n\ MIHrMIG3oAMCAQICFGNCMLUfhveEcLQmEnX2DqjwFZpGMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNjA4NTRaFw0yMDEwMDkxNjA4NTRaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoxkwFzAVBgNVHREEDjAMggp0ZXN0LmxvY2FsMAkG\n\ ByqGSM49BAEDJAAwIQIPAId8FJW00y8XSFmd2lBvAg5K6WAMIFgjhtwcRFcfQg==\n\ -----END CERTIFICATE-----"); /* /CN=other, SAN DNS:other.local */ X509 *certsandnsother = getcert("-----BEGIN CERTIFICATE-----\n\ MIHuMIG6oAMCAQICFAiFPNqpXcSIwxS0bfJZs8KDDafVMAkGByqGSM49BAEwEDEO\n\ MAwGA1UEAwwFb3RoZXIwHhcNMjAwOTI5MTYxMTM2WhcNMjAxMDA5MTYxMTM2WjAQ\n\ MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ NcK0IZozUpupFkD/dWBC37qIQW6jGjAYMBYGA1UdEQQPMA2CC290aGVyLmxvY2Fs\n\ MAkGByqGSM49BAEDJAAwIQIOTrQCgOkGcknZEchJFDgCDwCY84F0R2BnNEba95o9\n\ NA==\n\ -----END CERTIFICATE-----"); /* /CN=test, SAN IP Address:192.0.2.1 */ X509 *certsanip = getcert("-----BEGIN CERTIFICATE-----\n\ MIHlMIGxoAMCAQICFEukd75rE75+qB95Bo7fcb9wXlA9MAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkwNTQ5MjZaFw0yMDEwMDkwNTQ5MjZaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoxMwETAPBgNVHREECDAGhwTAAAIBMAkGByqGSM49\n\ BAEDJAAwIQIPALa7jf16ypPNHJSLiotwAg4DnSeToNmbqlRsvM80Aw==\n\ -----END CERTIFICATE-----"); /* /CN=other, SAN IP Address:192.0.2.2 */ X509 *certsanipother = getcert("-----BEGIN CERTIFICATE-----\n\ MIHmMIGzoAMCAQICFCYvcOo1Lqc+9JbYqfby1S9rJWufMAkGByqGSM49BAEwEDEO\n\ MAwGA1UEAwwFb3RoZXIwHhcNMjAwOTI5MTU0OTM2WhcNMjAxMDA5MTU0OTM2WjAQ\n\ MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ NcK0IZozUpupFkD/dWBC37qIQW6jEzARMA8GA1UdEQQIMAaHBMAAAgIwCQYHKoZI\n\ zj0EAQMjADAgAg5trehJeRpM04SJJZ6XnAIOFfzRRnQtm5rnsP+QBe8=\n\ -----END CERTIFICATE-----"); /* /CN=test, SAN IP Address:2001:DB8:0:0:0:0:0:1 */ X509 *certsanipv6 = getcert("-----BEGIN CERTIFICATE-----\n\ MIHxMIG9oAMCAQICFGhkABYXfolor1EF6Li3hDQeEVU+MAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNTU1NTZaFw0yMDEwMDkxNTU1NTZaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuox8wHTAbBgNVHREEFDAShxAgAQ24AAAAAAAAAAAA\n\ AAABMAkGByqGSM49BAEDJAAwIQIPAKsn++FWaDIcpnNBOFTuAg5C7gs7DxaNWgEu\n\ OrBTXA==\n\ -----END CERTIFICATE-----"); /* /CN=test, SAN DNS:192.0.2.1 */ X509 *certsanipindns = getcert("-----BEGIN CERTIFICATE-----\n\ MIHqMIG2oAMCAQICFFUjZGG96kpFI2fu90+jAhWsTr8YMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNTU4NDBaFw0yMDEwMDkxNTU4NDBaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoxgwFjAUBgNVHREEDTALggkxOTIuMC4yLjEwCQYH\n\ KoZIzj0EAQMkADAhAg5BngyplTbRlQ8o/oWWwQIPAL9SfgIaXi/gD6YlQCOU\n\ -----END CERTIFICATE-----"); /* /CN=test, SAN DNS:2001:DB8::1 */ X509 *certsanipv6indns = getcert("-----BEGIN CERTIFICATE-----\n\ MIHsMIG4oAMCAQICFFgnXltbOEGcWsS0vCv6Lsj4FhO3MAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNjAyMDRaFw0yMDEwMDkxNjAyMDRaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoxowGDAWBgNVHREEDzANggsyMDAxOmRiODo6MTAJ\n\ BgcqhkjOPQQBAyQAMCECDlWFhJxpHRgt93ZzN9k7Ag8Ag0YN+dL3MEIo2sqgRWg=\n\ -----END CERTIFICATE-----"); /* /CN=test, DNS:somethinglese, DNS:test.local, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1 */ X509 *certcomplex = getcert("-----BEGIN CERTIFICATE-----\n\ MIIBEjCB3qADAgECAhRgxyW7klgZvTf9isALCvwlVwvRtDAJBgcqhkjOPQQBMA8x\n\ DTALBgNVBAMMBHRlc3QwHhcNMjAwOTMwMDU1MjIyWhcNMjAxMDEwMDU1MjIyWjAP\n\ MQ0wCwYDVQQDDAR0ZXN0MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAEnGezNfbihAw1\n\ wrQhmjNSm6kWQP91YELfuohBbqNAMD4wPAYDVR0RBDUwM4INc29tZXRoaW5nbGVz\n\ ZYIKdGVzdC5sb2NhbIcEwAACAYcQIAENuAAAAAAAAAAAAAAAATAJBgcqhkjOPQQB\n\ AyQAMCECDlTfJfMJElZZgvUdkatdAg8ApiXkPXLXXrV6OMRG9us=\n\ -----END CERTIFICATE-----"); /* /CN=test, DNS:somethinglese, DNS:other.local, IP Address:192.0.2.2, IP Address:2001:DB8:0:0:0:0:0:2 */ X509 *certcomplexother = getcert("-----BEGIN CERTIFICATE-----\n\ MIIBFTCB4aADAgECAhR0GSgeV7pqQnbHRgv5y5plz/6+NjAJBgcqhkjOPQQBMBAx\n\ DjAMBgNVBAMMBW90aGVyMB4XDTIwMDkzMDA1NTI1NVoXDTIwMTAxMDA1NTI1NVow\n\ EDEOMAwGA1UEAwwFb3RoZXIwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKE\n\ DDXCtCGaM1KbqRZA/3VgQt+6iEFuo0EwPzA9BgNVHREENjA0gg1zb21ldGhpbmds\n\ ZXNlggtvdGhlci5sb2NhbIcEwAACAocQIAENuAAAAAAAAAAAAAAAAjAJBgcqhkjO\n\ PQQBAyQAMCECDwCEaHL6oHT4zwH6jD91YwIOYO3L8cHIzmnGCOJYIQ4=\n\ -----END CERTIFICATE-----"); /* /CN=test, URI:https://test.local/profile#me */ X509 *certsanuri = getcert("-----BEGIN CERTIFICATE-----\n\ MIH9MIHKoAMCAQICFHsSOjcYexRKQpNlH1oHV1cxvdgHMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEwMDYwODU5MzRaFw0yMDEwMTYwODU5MzRaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoywwKjAoBgNVHREEITAfhh1odHRwczovL3Rlc3Qu\n\ bG9jYWwvcHJvZmlsZSNtZTAJBgcqhkjOPQQBAyMAMCACDniwUmV285CoguiJ6WmW\n\ Ag5ZWNTJtmNNdKxh0Mahsw==\n\ -----END CERTIFICATE-----"); /* /CN=other, URI:https://other.local/profile#me */ X509 *certsanuriother = getcert("-----BEGIN CERTIFICATE-----\n\ MIIBATCBzaADAgECAhQLG7rYpl+8YbPNEtUgw6HRZYIc1DAJBgcqhkjOPQQBMBAx\n\ DjAMBgNVBAMMBW90aGVyMB4XDTIwMTAwNjA5MDU0OVoXDTIwMTAxNjA5MDU0OVow\n\ EDEOMAwGA1UEAwwFb3RoZXIwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKE\n\ DDXCtCGaM1KbqRZA/3VgQt+6iEFuoy0wKzApBgNVHREEIjAghh5odHRwczovL290\n\ aGVyLmxvY2FsL3Byb2ZpbGUjbWUwCQYHKoZIzj0EAQMkADAhAg8AoOJVnRcp3gyY\n\ Qe0Vy/UCDijCHK6Y5GkzWD7H008l\n\ -----END CERTIFICATE-----"); /* /CN=test, Registered ID:1.2.3.4 */ X509 *certsanrid = getcert("-----BEGIN CERTIFICATE-----\n\ MIHjMIGwoAMCAQICFBKq59XodNaMiLZDZbE7BMFn+GnAMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEwMDYxNTA1NTBaFw0yMDEwMTYxNTA1NTBaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoxIwEDAOBgNVHREEBzAFiAMqAwQwCQYHKoZIzj0E\n\ AQMjADAgAg4QFOirxwoC5OYpFArE8gIORG+zCoikzhvY95kBGvg=\n\ -----END CERTIFICATE-----"); /* /CN=other, Registered ID:1.2.3.9 */ X509 *certsanridother = getcert("-----BEGIN CERTIFICATE-----\n\ MIHmMIGyoAMCAQICFEvhI4VZvPr7cITrckvz6J576uy3MAkGByqGSM49BAEwEDEO\n\ MAwGA1UEAwwFb3RoZXIwHhcNMjAxMDA2MTUwNzQzWhcNMjAxMDE2MTUwNzQzWjAQ\n\ MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ NcK0IZozUpupFkD/dWBC37qIQW6jEjAQMA4GA1UdEQQHMAWIAyoDCTAJBgcqhkjO\n\ PQQBAyQAMCECDwCJMMBtTsOZNwvy43TlLgIOKtssl/hBDN/JcPbBQgI=\n\ -----END CERTIFICATE-----"); /* /CN=test, otherNAME 1.3.6.1.5.5.7.8.8;UTF8:test.local */ X509 *certsanothername = getcert("-----BEGIN CERTIFICATE-----\n\ MIH4MIHFoAMCAQICFHfn1oV2cr4BkkWImdYCJXkSmiKrMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEwMDYxNTE4NTNaFw0yMDEwMTYxNTE4NTNaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoycwJTAjBgNVHREEHDAaoBgGCCsGAQUFBwgIoAwM\n\ CnRlc3QubG9jYWwwCQYHKoZIzj0EAQMjADAgAg5picQbJfIM1Ljn7H/26QIOCLcA\n\ UXfI8XA07aHTgzE=\n\ -----END CERTIFICATE-----"); /* /CN=other, otherNAME 1.3.6.1.5.5.7.8.8;UTF8:other.local */ X509 *certsanothernameother = getcert("-----BEGIN CERTIFICATE-----\n\ MIH6MIHGoAMCAQICFEa/hIvgCkqCF6ulCq3Jy3iw6XkwMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEwMDYxNTIwMDhaFw0yMDEwMTYxNTIwMDhaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuoygwJjAkBgNVHREEHTAboBkGCCsGAQUFBwgIoA0M\n\ C290aGVyLmxvY2FsMAkGByqGSM49BAEDJAAwIQIOSOJ5OK2xzjrCweD/ImECDwDL\n\ COiok62ckBQsaUG8AA==\n\ -----END CERTIFICATE-----"); /* /CN=test, DNS:test.local, Registered ID:1.2.3.4 */ X509 *certmulti = getcert("-----BEGIN CERTIFICATE-----\n\ MIHxMIG8oAMCAQICFFrDaNQffsxLTERNbN7sXupYziWAMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEyMTgwOTQwMDFaFw0yMTAxMTcwOTQwMDFaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ tCGaM1KbqRZA/3VgQt+6iEFuox4wHDAaBgNVHREEEzARggp0ZXN0LmxvY2FsiAMq\n\ AwQwCQYHKoZIzj0EAQMlADAiAg8AnsiRL2CH3u0bAX/FOt4CDwC9wGzr0l/PCnxK\n\ mKlpkQ==\n\ -----END CERTIFICATE-----"); /* /CN=other, DNS:other.local, Registered ID:1.2.3.4 */ X509 *certmultiother = getcert("-----BEGIN CERTIFICATE-----\n\ MIHyMIG/oAMCAQICFAke6IO1yAeuwOewT/QfAF9afFo7MAkGByqGSM49BAEwEDEO\n\ MAwGA1UEAwwFb3RoZXIwHhcNMjAxMjE4MDk0NTI1WhcNMjEwMTE3MDk0NTI1WjAQ\n\ MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ NcK0IZozUpupFkD/dWBC37qIQW6jHzAdMBsGA1UdEQQUMBKCC290aGVyLmxvY2Fs\n\ iAMqAwQwCQYHKoZIzj0EAQMjADAgAg521Y8BtyeKAMIY8lcLbwIORNNmcwVIJjGj\n\ vY/uPjA=\n\ -----END CERTIFICATE-----"); memset(&conf, 0, sizeof(conf)); conf.hostports = list_create(); debug_init("t_verify_cert"); debug_set_level(5); /* test check disabled*/ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 0; hp.host = "test"; hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsimple, &conf, &hp), "check disabled"); while (list_shift(conf.hostports)) ; } /* test no check if prefixlen != 255 (CIDR) */ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 1; hp.host = "0.0.0.0/0"; hp.prefixlen = 0; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsimple, &conf, &hp), "cidr prefix"); while (list_shift(conf.hostports)) ; } /* test simple match for CN=test */ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 1; hp.host = "test"; hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsimple, &conf, &hp), "simple cert cn"); ok(0, verifyconfcert(certsimpleother, &conf, &hp), "negative simple cert cn"); /* as per RFC 6125 6.4.4: CN MUST NOT be matched if SAN is present */ ok(0, verifyconfcert(certsandns, &conf, &hp), "simple cert cn vs san dns, RFC6125"); while (list_shift(conf.hostports)) ; } /* test literal ip match to SAN IP */ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 1; hp.host = "192.0.2.1"; getaddrinfo(hp.host, NULL, NULL, &hp.addrinfo); hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsanip, &conf, &hp), "san ip"); ok(0, verifyconfcert(certsanipother, &conf, &hp), "wrong san ip"); ok(0, verifyconfcert(certsimple, &conf, &hp), "negative san ip"); ok(1, verifyconfcert(certsanipindns, &conf, &hp), "san ip in dns"); ok(1, verifyconfcert(certcomplex, &conf, &hp), "san ip in complex cert"); freeaddrinfo(hp.addrinfo); while (list_shift(conf.hostports)) ; } /* test literal ipv6 match to SAN IP */ { struct hostportres hp; memset(&hp, 0, sizeof(struct hostportres)); conf.name = "test"; conf.certnamecheck = 1; hp.host = "2001:db8::1"; getaddrinfo(hp.host, NULL, NULL, &hp.addrinfo); hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsanipv6, &conf, &hp), "san ipv6"); ok(0, verifyconfcert(certsanipother, &conf, &hp), "wrong san ipv6"); ok(0, verifyconfcert(certsimple, &conf, &hp), "negative san ipv6"); ok(1, verifyconfcert(certsanipv6indns, &conf, &hp), "san ipv6 in dns"); ok(1, verifyconfcert(certcomplex, &conf, &hp), "san ipv6 in complex cert"); freeaddrinfo(hp.addrinfo); while (list_shift(conf.hostports)) ; } /* test simple match for SAN DNS:test.local */ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 1; hp.host = "test.local"; hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, verifyconfcert(certsandns, &conf, &hp), "san dns"); ok(0, verifyconfcert(certsandnsother, &conf, &hp), "negative san dns"); ok(1, verifyconfcert(certcomplex, &conf, &hp), "san dns in complex cert"); ok(0, verifyconfcert(certsimple, &conf, &hp), "missing san dns"); while (list_shift(conf.hostports)) ; } /* test multiple hostports san dns(match in second) */ { struct hostportres hp1, hp2; conf.name = "test"; conf.certnamecheck = 1; hp1.host = "test.none"; hp1.prefixlen = 255; list_push(conf.hostports, &hp1); hp2.host = "test"; hp2.prefixlen = 255; list_push(conf.hostports, &hp2); ok(1, verifyconfcert(certsimple, &conf, NULL), "multi hostport cn"); ok(0, verifyconfcert(certsimpleother, &conf, NULL), "negative multi hostport cn"); while (list_shift(conf.hostports)) ; } /* test multiple hostports san dns(match in second) */ { struct hostportres hp1, hp2; conf.name = "test"; conf.certnamecheck = 1; hp1.host = "test.none"; hp1.prefixlen = 255; list_push(conf.hostports, &hp1); hp2.host = "test.local"; hp2.prefixlen = 255; list_push(conf.hostports, &hp2); ok(1, verifyconfcert(certsandns, &conf, NULL), "multi hostport san dns"); ok(0, verifyconfcert(certsandnsother, &conf, NULL), "negative multi hostport san dns"); ok(1, verifyconfcert(certcomplex, &conf, NULL), "multi hostport san dns in complex cert"); ok(0, verifyconfcert(certsandns, &conf, &hp1), "multi hostport explicit wrong cert"); ok(1, verifyconfcert(certsandns, &conf, &hp2), "multi hostport explicit matching cert"); ok(0, verifyconfcert(certcomplex, &conf, &hp1), "multi hostport explicit wrong complex cert"); ok(1, verifyconfcert(certcomplex, &conf, &hp2), "multi hostport explicit matching complex cert"); while (list_shift(conf.hostports)) ; } /* test explicit CN regex */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "CN:/t..t/"), "explicit cn regex config"); ok(1, verifyconfcert(certsimple, &conf, NULL), "explicit cn regex"); ok(0, verifyconfcert(certsimpleother, &conf, NULL), "negative explicit cn regex"); ok(1, verifyconfcert(certsandns, &conf, NULL), "explicit cn regex with SAN DNS"); freematchcertattr(&conf); } /* test explicit ip match to SAN IP */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:IP:192.0.2.1"), "explicit san ip config"); ok(1, verifyconfcert(certsanip, &conf, NULL), "explicit san ip"); ok(0, verifyconfcert(certsanipother, &conf, NULL), "wrong explicit san ip"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicit san ip"); ok(1, verifyconfcert(certcomplex, &conf, NULL), "explicit san ip in complex cert"); freematchcertattr(&conf); } /* test explicit ipv6 match to SAN IP */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:IP:2001:db8::1"), "explicit san ipv6 config"); ok(1, verifyconfcert(certsanipv6, &conf, NULL), "explicit san ipv6"); ok(0, verifyconfcert(certsanipother, &conf, NULL), "wrong explicit san ipv6"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicitsan ipv6"); ok(1, verifyconfcert(certcomplex, &conf, NULL), "explicit san ipv6 in complex cert"); freematchcertattr(&conf); } /* test explicit SAN DNS regex */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:DNS:/t..t\\.local/"), "explicit san dns regex config"); ok(1, verifyconfcert(certsandns, &conf, NULL), "explicit san dns"); ok(0, verifyconfcert(certsandnsother, &conf, NULL), "negative explicit san dns"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicit san dns"); ok(1, verifyconfcert(certcomplex, &conf, NULL), "explicit san dns in complex cert"); freematchcertattr(&conf); } /* test explicit SAN URI regex */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:URI:/https:\\/\\/test.local\\/profile#me/"), "explicit cn regex config"); ok(1, verifyconfcert(certsanuri, &conf, NULL), "explicit san uri regex"); ok(0, verifyconfcert(certsanuriother, &conf, NULL), "negative explicit san uri"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicit san uri"); freematchcertattr(&conf); } /* test explicit SAN rID */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:rID:1.2.3.4"), "explicit san rid config"); ok(1, verifyconfcert(certsanrid, &conf, NULL), "explicit san rid"); ok(0, verifyconfcert(certsanridother, &conf, NULL), "negative explicit san rid"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicit san rid"); freematchcertattr(&conf); } /* test explicit SAN otherNAME */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "SubjectAltName:otherName:1.3.6.1.5.5.7.8.8:/test.local/"), "explicit san otherName config"); ok(1, verifyconfcert(certsanothername, &conf, NULL), "explicit san otherName"); ok(0, verifyconfcert(certsanothernameother, &conf, NULL), "negative explicit san otherName"); ok(0, verifyconfcert(certsimple, &conf, NULL), "missing explicit san otherName"); freematchcertattr(&conf); } /* test valid config syntax */ { conf.name = "test"; conf.certnamecheck = 0; ok(1, addmatchcertattr(&conf, "CN:/t..t"), "test regex config syntax"); ok(1, verifyconfcert(certsimple, &conf, NULL), "test regex config syntax execution"); freematchcertattr(&conf); } /* test invalid config syntax */ { conf.name = "test"; conf.certnamecheck = 0; ok(0, addmatchcertattr(&conf, "CN:t..t"), "test invalid syntax regex"); freematchcertattr(&conf); ok(0, addmatchcertattr(&conf, "SAN:/t..t/"), "test invalid syntax attribute"); freematchcertattr(&conf); ok(0, addmatchcertattr(&conf, "SubjectAltName:IP:1.2.3"), "test invalid syntax ip"); freematchcertattr(&conf); ok(0, addmatchcertattr(&conf, "SubjectAltName:IP:2001:db8:1"), "test invalid syntax ipv6"); freematchcertattr(&conf); ok(0, addmatchcertattr(&conf, "SubjectAltName:rID:1:2"), "test invalid syntax rID"); freematchcertattr(&conf); } /* test explicit & implicit combined */ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 1; hp.host = "test.local"; hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, addmatchcertattr(&conf, "CN:/t..t"), "combined config"); ok(1, verifyconfcert(certsandns, &conf, &hp), "combined san dns"); ok(0, verifyconfcert(certsandnsother, &conf, &hp), "negative combined san dns"); ok(1, verifyconfcert(certcomplex, &conf, &hp), "combined san dns in complex cert"); ok(0, verifyconfcert(certsimple, &conf, &hp), "combined missing san dns"); while (list_shift(conf.hostports)) ; freematchcertattr(&conf); } /* test multiple explicit checks*/ { struct hostportres hp; conf.name = "test"; conf.certnamecheck = 0; hp.host = "test.local"; hp.prefixlen = 255; list_push(conf.hostports, &hp); ok(1, addmatchcertattr(&conf, "SubjectAltName:DNS:/test\\.local/"), "multiple check 1"); ok(1, addmatchcertattr(&conf, "SubjectAltName:rID:1.2.3.4"), "multiple check 2"); ok(0, verifyconfcert(certsandns, &conf, &hp), "multiple missing rID"); ok(0, verifyconfcert(certsanrid, &conf, &hp), "multiple missing DNS"); ok(1, verifyconfcert(certmulti, &conf, &hp), "multiple SANs"); ok(0, verifyconfcert(certmultiother, &conf, &hp), "multiple negative match"); ok(0, verifyconfcert(certcomplex, &conf, &hp), "multiple missing rID in complex cert"); ok(0, verifyconfcert(certsimple, &conf, &hp), "multiple missing everything"); while (list_shift(conf.hostports)) ; freematchcertattr(&conf); } printf("1..%d\n", numtests); list_free(conf.hostports); X509_free(certsimple); X509_free(certsimpleother); X509_free(certsandns); X509_free(certsandnsother); X509_free(certsanip); X509_free(certsanipother); X509_free(certsanipindns); X509_free(certsanipv6); X509_free(certsanipv6indns); X509_free(certcomplex); X509_free(certcomplexother); X509_free(certsanuri); X509_free(certsanuriother); X509_free(certsanrid); X509_free(certsanridother); X509_free(certsanothername); X509_free(certsanothernameother); X509_free(certmulti); X509_free(certmultiother); return 0; } radsecproxy-1.11.1/tests/t_rewrite_config.c0000644000076600000240000000473514722543325014475 /* Copyright (C) 2019, SWITCH */ /* See LICENSE for licensing information. */ #include "../debug.h" #include "../radmsg.h" #include "../rewrite.h" #include "../util.h" #include #include #include int main(int argc, char *argv[]) { struct rewrite *result; char *rewritename = "rewrite"; char **addattrs; int numtests = 2, i; struct tlv *tlv, *expected; uint8_t expectedvalue[] = {'1', 0, 0, '1', 'A', '%', '4', '1'}; printf("1..%d\n", numtests); numtests = 1; { addattrs = malloc(2 * sizeof(char *)); addattrs[0] = stringcopy("1:'1%00%001%41%2541", 0); addattrs[1] = NULL; expected = maketlv(1, 8, expectedvalue); addrewrite(rewritename, 0, NULL, NULL, addattrs, NULL, NULL, NULL, NULL, NULL); result = getrewrite(rewritename, NULL); if (result->addattrs->first) { tlv = (struct tlv *)result->addattrs->first->data; if (!eqtlv(tlv, expected)) { printf("tlv value was: 0x"); for (i = 0; i < tlv->l; i++) { printf("%x", *((tlv->v) + i)); } printf("\n"); printf("not "); } printf("ok %d - rewrite config\n", numtests++); } else { printf("not ok %d - rewrite config\n", numtests++); } freetlv(expected); } /* test issue #62 */ { char *expectreplace = "\\1=86400"; char **modvattrs = malloc(2 * sizeof(char *)); rewritename = "issue62"; modvattrs[0] = stringcopy("9:102:/^(h323-credit-time).*$/\\1=86400/", 0); modvattrs[1] = NULL; addrewrite(rewritename, 0, NULL, NULL, NULL, NULL, NULL, modvattrs, NULL, NULL); result = getrewrite(rewritename, NULL); if (result && result->modvattrs && result->modvattrs->first) { struct modattr *mod = (struct modattr *)result->modvattrs->first->data; if (regexec(mod->regex, "h323-credit-time=1846422", 0, NULL, 0)) { printf("not "); } if (strcmp(mod->replacement, expectreplace)) { printf("not "); } else if (mod->t != 102 || mod->vendor != 9) { printf("not "); } printf("ok %d - rewrite config issue #62\n", numtests++); } else { printf("not ok %d - rewrite config issue #62\n", numtests++); } } return 0; } radsecproxy-1.11.1/tests/Makefile.in0000644000076600000240000011164114724611067013041 # Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = t_fticks$(EXEEXT) t_rewrite$(EXEEXT) \ t_resizeattr$(EXEEXT) t_rewrite_config$(EXEEXT) \ t_verify_cert$(EXEEXT) t_radmsg$(EXEEXT) t_unhex$(EXEEXT) \ t_utf8$(EXEEXT) t_verify_eap$(EXEEXT) subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/ax_check_openssl.m4 \ $(top_srcdir)/ax_build_date_epoch.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = t_fticks_SOURCES = t_fticks.c t_fticks_OBJECTS = t_fticks.$(OBJEXT) t_fticks_LDADD = $(LDADD) t_fticks_DEPENDENCIES = $(top_builddir)/librsp.a t_radmsg_SOURCES = t_radmsg.c t_radmsg_OBJECTS = t_radmsg.$(OBJEXT) t_radmsg_LDADD = $(LDADD) t_radmsg_DEPENDENCIES = $(top_builddir)/librsp.a t_resizeattr_SOURCES = t_resizeattr.c t_resizeattr_OBJECTS = t_resizeattr.$(OBJEXT) t_resizeattr_LDADD = $(LDADD) t_resizeattr_DEPENDENCIES = $(top_builddir)/librsp.a t_rewrite_SOURCES = t_rewrite.c t_rewrite_OBJECTS = t_rewrite.$(OBJEXT) t_rewrite_LDADD = $(LDADD) t_rewrite_DEPENDENCIES = $(top_builddir)/librsp.a t_rewrite_config_SOURCES = t_rewrite_config.c t_rewrite_config_OBJECTS = t_rewrite_config.$(OBJEXT) t_rewrite_config_LDADD = $(LDADD) t_rewrite_config_DEPENDENCIES = $(top_builddir)/librsp.a t_unhex_SOURCES = t_unhex.c t_unhex_OBJECTS = t_unhex.$(OBJEXT) t_unhex_LDADD = $(LDADD) t_unhex_DEPENDENCIES = $(top_builddir)/librsp.a t_utf8_SOURCES = t_utf8.c t_utf8_OBJECTS = t_utf8.$(OBJEXT) t_utf8_LDADD = $(LDADD) t_utf8_DEPENDENCIES = $(top_builddir)/librsp.a t_verify_cert_SOURCES = t_verify_cert.c t_verify_cert_OBJECTS = t_verify_cert.$(OBJEXT) t_verify_cert_LDADD = $(LDADD) t_verify_cert_DEPENDENCIES = $(top_builddir)/librsp.a t_verify_eap_SOURCES = t_verify_eap.c t_verify_eap_OBJECTS = t_verify_eap.$(OBJEXT) t_verify_eap_LDADD = $(LDADD) t_verify_eap_DEPENDENCIES = $(top_builddir)/librsp.a AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/t_fticks.Po ./$(DEPDIR)/t_radmsg.Po \ ./$(DEPDIR)/t_resizeattr.Po ./$(DEPDIR)/t_rewrite.Po \ ./$(DEPDIR)/t_rewrite_config.Po ./$(DEPDIR)/t_unhex.Po \ ./$(DEPDIR)/t_utf8.Po ./$(DEPDIR)/t_verify_cert.Po \ ./$(DEPDIR)/t_verify_eap.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = t_fticks.c t_radmsg.c t_resizeattr.c t_rewrite.c \ t_rewrite_config.c t_unhex.c t_utf8.c t_verify_cert.c \ t_verify_eap.c DIST_SOURCES = t_fticks.c t_radmsg.c t_resizeattr.c t_rewrite.c \ t_rewrite_config.c t_unhex.c t_utf8.c t_verify_cert.c \ t_verify_eap.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @OPENSSL_LDFLAGS@ @TARGET_LDFLAGS@ @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RELEASEDATE = @RELEASEDATE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ TARGET_CFLAGS = @TARGET_CFLAGS@ TARGET_LDFLAGS = @TARGET_LDFLAGS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign #LOG_DRIVER = ./tap-driver.sh LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ $(top_srcdir)/build-aux/tap-driver.sh AM_CFLAGS = -g -Wall -Werror @OPENSSL_INCLUDES@ @TARGET_CFLAGS@ LDADD = $(top_builddir)/librsp.a @OPENSSL_LIBS@ TESTS = $(check_PROGRAMS) all: all-am .SUFFIXES: .SUFFIXES: .c .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) t_fticks$(EXEEXT): $(t_fticks_OBJECTS) $(t_fticks_DEPENDENCIES) $(EXTRA_t_fticks_DEPENDENCIES) @rm -f t_fticks$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_fticks_OBJECTS) $(t_fticks_LDADD) $(LIBS) t_radmsg$(EXEEXT): $(t_radmsg_OBJECTS) $(t_radmsg_DEPENDENCIES) $(EXTRA_t_radmsg_DEPENDENCIES) @rm -f t_radmsg$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_radmsg_OBJECTS) $(t_radmsg_LDADD) $(LIBS) t_resizeattr$(EXEEXT): $(t_resizeattr_OBJECTS) $(t_resizeattr_DEPENDENCIES) $(EXTRA_t_resizeattr_DEPENDENCIES) @rm -f t_resizeattr$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_resizeattr_OBJECTS) $(t_resizeattr_LDADD) $(LIBS) t_rewrite$(EXEEXT): $(t_rewrite_OBJECTS) $(t_rewrite_DEPENDENCIES) $(EXTRA_t_rewrite_DEPENDENCIES) @rm -f t_rewrite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_rewrite_OBJECTS) $(t_rewrite_LDADD) $(LIBS) t_rewrite_config$(EXEEXT): $(t_rewrite_config_OBJECTS) $(t_rewrite_config_DEPENDENCIES) $(EXTRA_t_rewrite_config_DEPENDENCIES) @rm -f t_rewrite_config$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_rewrite_config_OBJECTS) $(t_rewrite_config_LDADD) $(LIBS) t_unhex$(EXEEXT): $(t_unhex_OBJECTS) $(t_unhex_DEPENDENCIES) $(EXTRA_t_unhex_DEPENDENCIES) @rm -f t_unhex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_unhex_OBJECTS) $(t_unhex_LDADD) $(LIBS) t_utf8$(EXEEXT): $(t_utf8_OBJECTS) $(t_utf8_DEPENDENCIES) $(EXTRA_t_utf8_DEPENDENCIES) @rm -f t_utf8$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_utf8_OBJECTS) $(t_utf8_LDADD) $(LIBS) t_verify_cert$(EXEEXT): $(t_verify_cert_OBJECTS) $(t_verify_cert_DEPENDENCIES) $(EXTRA_t_verify_cert_DEPENDENCIES) @rm -f t_verify_cert$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_verify_cert_OBJECTS) $(t_verify_cert_LDADD) $(LIBS) t_verify_eap$(EXEEXT): $(t_verify_eap_OBJECTS) $(t_verify_eap_DEPENDENCIES) $(EXTRA_t_verify_eap_DEPENDENCIES) @rm -f t_verify_eap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_verify_eap_OBJECTS) $(t_verify_eap_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_fticks.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_radmsg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_resizeattr.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_rewrite.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_rewrite_config.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_unhex.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_utf8.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_verify_cert.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_verify_eap.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? t_fticks.log: t_fticks$(EXEEXT) @p='t_fticks$(EXEEXT)'; \ b='t_fticks'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_rewrite.log: t_rewrite$(EXEEXT) @p='t_rewrite$(EXEEXT)'; \ b='t_rewrite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_resizeattr.log: t_resizeattr$(EXEEXT) @p='t_resizeattr$(EXEEXT)'; \ b='t_resizeattr'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_rewrite_config.log: t_rewrite_config$(EXEEXT) @p='t_rewrite_config$(EXEEXT)'; \ b='t_rewrite_config'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_verify_cert.log: t_verify_cert$(EXEEXT) @p='t_verify_cert$(EXEEXT)'; \ b='t_verify_cert'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_radmsg.log: t_radmsg$(EXEEXT) @p='t_radmsg$(EXEEXT)'; \ b='t_radmsg'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_unhex.log: t_unhex$(EXEEXT) @p='t_unhex$(EXEEXT)'; \ b='t_unhex'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_utf8.log: t_utf8$(EXEEXT) @p='t_utf8$(EXEEXT)'; \ b='t_utf8'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) t_verify_eap.log: t_verify_eap$(EXEEXT) @p='t_verify_eap$(EXEEXT)'; \ b='t_verify_eap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/t_fticks.Po -rm -f ./$(DEPDIR)/t_radmsg.Po -rm -f ./$(DEPDIR)/t_resizeattr.Po -rm -f ./$(DEPDIR)/t_rewrite.Po -rm -f ./$(DEPDIR)/t_rewrite_config.Po -rm -f ./$(DEPDIR)/t_unhex.Po -rm -f ./$(DEPDIR)/t_utf8.Po -rm -f ./$(DEPDIR)/t_verify_cert.Po -rm -f ./$(DEPDIR)/t_verify_eap.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/t_fticks.Po -rm -f ./$(DEPDIR)/t_radmsg.Po -rm -f ./$(DEPDIR)/t_resizeattr.Po -rm -f ./$(DEPDIR)/t_rewrite.Po -rm -f ./$(DEPDIR)/t_rewrite_config.Po -rm -f ./$(DEPDIR)/t_unhex.Po -rm -f ./$(DEPDIR)/t_utf8.Po -rm -f ./$(DEPDIR)/t_verify_cert.Po -rm -f ./$(DEPDIR)/t_verify_eap.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: radsecproxy-1.11.1/tests/t_utf8.c0000644000076600000240000001475514722543325012360 /* Copyright (C) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "../util.h" #include #include int main(int argc, char *argv[]) { int testcount = 0; { char *str = "test"; if (verifyutf8((uint8_t *)str, strlen(str)) != 1) printf("not "); printf("ok %d - simple test ascii\n", ++testcount); } { char *str = "smile 😀"; if (verifyutf8((uint8_t *)str, strlen(str)) != 1) printf("not "); printf("ok %d - original utf8 string\n", ++testcount); } { uint8_t str[] = {0x00, 'x', 0x00}; if (verifyutf8(str, 2) != 0) printf("not "); printf("ok %d - simple test null char\n", ++testcount); } { uint8_t str[] = {0x01, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - control characters first\n", ++testcount); } { uint8_t str[] = {0x1F, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - control characters last\n", ++testcount); } { uint8_t str[] = {0x7F, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - delete\n", ++testcount); } { uint8_t str[] = {'t', 0x00, 's', 't', 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - invalid 2nd char\n", ++testcount); } { uint8_t str[] = {'t', 'e', 0x00, 't', 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - invalid 3rd char\n", ++testcount); } { uint8_t str[] = {'t', 'e', 's', 0x00, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - invalid 4th char\n", ++testcount); } { uint8_t str[] = {0x80, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - invalid continuation single byte\n", ++testcount); } { uint8_t str[] = {0xFF, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - invalid byte\n", ++testcount); } { uint8_t str[] = {0xC2, 0xA0, 0x00}; if (verifyutf8(str, 2) != 1) printf("not "); printf("ok %d - 2-byte char first codepoint\n", ++testcount); } { uint8_t str[] = {0xDF, 0xBF, 0x00}; if (verifyutf8(str, 2) != 1) printf("not "); printf("ok %d - 2-byte char last codepoint\n", ++testcount); } { uint8_t str[] = {0xC0, 0x80, 0x00}; if (verifyutf8(str, 2) != 0) printf("not "); printf("ok %d - overlong 1-byte\n", ++testcount); } { uint8_t str[] = {0xC2, 0x80, 0x00}; if (verifyutf8(str, 2) != 0) printf("not "); printf("ok %d - 2-byte control first\n", ++testcount); } { uint8_t str[] = {0xC2, 0x9F, 0x00}; if (verifyutf8(str, 2) != 0) printf("not "); printf("ok %d - 2-byte control last\n", ++testcount); } { uint8_t str[] = {0xE0, 0xA0, 0x80, 0x00}; if (verifyutf8(str, 3) != 1) printf("not "); printf("ok %d - 3-byte char first codepoint\n", ++testcount); } { uint8_t str[] = {0xEF, 0xBF, 0xBF, 0x00}; if (verifyutf8(str, 3) != 1) printf("not "); printf("ok %d - 3-byte char last codepoint\n", ++testcount); } { uint8_t str[] = {0xE0, 0x80, 0x80, 0x00}; if (verifyutf8(str, 3) != 0) printf("not "); printf("ok %d - 3-byte char invalid 1\n", ++testcount); } { uint8_t str[] = {0xED, 0xA0, 0xBF, 0x00}; if (verifyutf8(str, 3) != 0) printf("not "); printf("ok %d - 3-byte char invalid 2\n", ++testcount); } { uint8_t str[] = {0xF0, 0x90, 0x80, 0x80, 0x00}; if (verifyutf8(str, 4) != 1) printf("not "); printf("ok %d - 4-byte char first codepoint\n", ++testcount); } { uint8_t str[] = {0xF4, 0x8F, 0xBF, 0xBF, 0x00}; if (verifyutf8(str, 4) != 1) printf("not "); printf("ok %d - 4-byte char first codepoint\n", ++testcount); } { uint8_t str[] = {0xF0, 0x80, 0x80, 0x80, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid 1\n", ++testcount); } { uint8_t str[] = {0xF4, 0x90, 0x80, 0x80, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid 2\n", ++testcount); } { uint8_t str[] = {0xF7, 0xBF, 0xBF, 0xBF, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid 3\n", ++testcount); } { uint8_t str[] = {0xFF, 0xBF, 0xBF, 0xBF, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char all ones\n", ++testcount); } { uint8_t str[] = {0xC2, 0x80, 0x00}; if (verifyutf8(str, 1) != 0) printf("not "); printf("ok %d - 2-byte char too short\n", ++testcount); } { uint8_t str[] = {0xC2, 0x80, 0x80, 0x00}; if (verifyutf8(str, 3) != 0) printf("not "); printf("ok %d - 2-byte char too long\n", ++testcount); } { uint8_t str[] = {0xC2, 0x80, 0x00, 0x00}; if (verifyutf8(str, 3) != 0) printf("not "); printf("ok %d - invalid after 2-byte char\n", ++testcount); } { uint8_t str[] = {0xF0, 'x', 0x80, 0x80, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid continuation 2nd byte\n", ++testcount); } { uint8_t str[] = {0xF0, 0x90, 'x', 0x80, 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid continuation 3rd byte\n", ++testcount); } { uint8_t str[] = {0xF0, 0x90, 0x80, 'x', 0x00}; if (verifyutf8(str, 4) != 0) printf("not "); printf("ok %d - 4-byte char invalid continuation 4th byte\n", ++testcount); } { uint8_t str[] = {'t', 'e', 's', 't', 0xF0, 0x91, 0x82, 0x83, 'x', 'y', 'z', 0x00}; if (verifyutf8(str, 11) != 1) printf("not "); printf("ok %d - long string\n", ++testcount); } printf("1..%d\n", testcount); return 0; } radsecproxy-1.11.1/radmsg.h0000644000076600000240000000706614722543325011264 /* Copyright (c) 2007-2008, UNINETT AS * Copyright (c) 2015, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #ifndef _RADMSG_H #define _RADMSG_H #include "tlv11.h" #include #define RAD_Min_Length 20 #define RAD_Max_Length 4096 #define RAD_Max_Attr_Value_Length 253 #define RAD_Access_Request 1 #define RAD_Access_Accept 2 #define RAD_Access_Reject 3 #define RAD_Accounting_Request 4 #define RAD_Accounting_Response 5 #define RAD_Access_Challenge 11 #define RAD_Status_Server 12 #define RAD_Status_Client 13 #define RAD_Disconnect_Request 40 #define RAD_Disconnect_ACK 41 #define RAD_Disconnect_NAK 42 #define RAD_CoA_Request 43 #define RAD_CoA_ACK 44 #define RAD_CoA_NAK 45 #define RAD_Attr_User_Name 1 #define RAD_Attr_User_Password 2 #define RAD_Attr_CHAP_Password 3 #define RAD_Attr_NAS_IP_Address 4 #define RAD_Attr_Framed_IP_Address 8 #define RAD_Attr_Reply_Message 18 #define RAD_Attr_Vendor_Specific 26 #define RAD_Attr_Called_Station_Id 30 #define RAD_Attr_Calling_Station_Id 31 #define RAD_Attr_Proxy_State 33 #define RAD_Attr_Acct_Status_Type 40 #define RAD_Attr_Acct_Input_Octets 42 #define RAD_Attr_Acct_Output_Octets 43 #define RAD_Attr_Acct_Session_Id 44 #define RAD_Attr_Acct_Session_Time 46 #define RAD_Attr_Acct_Input_Packets 47 #define RAD_Attr_Acct_Output_Packets 48 #define RAD_Attr_Acct_Terminate_Cause 49 #define RAD_Attr_Event_Timestamp 55 #define RAD_Attr_CHAP_Challenge 60 #define RAD_Attr_Tunnel_Password 69 #define RAD_Attr_EAP_Message 79 #define RAD_Attr_Message_Authenticator 80 #define RAD_Attr_CUI 89 #define RAD_Attr_Error_Cause 101 #define RAD_Attr_Operator_Name 126 #define RAD_Acct_Status_Start 1 #define RAD_Acct_Status_Stop 2 #define RAD_Acct_Status_Alive 3 #define RAD_Acct_Status_Interim_Update 3 #define RAD_Acct_Status_Accounting_On 7 #define RAD_Acct_Status_Accounting_Off 8 #define RAD_Acct_Status_Failed 15 #define RAD_Err_Unsupported_Extension 406 #define RAD_VS_ATTR_MS_MPPE_Send_Key 16 #define RAD_VS_ATTR_MS_MPPE_Recv_Key 17 struct radmsg { uint8_t code; uint8_t id; uint8_t auth[20]; struct list *attrs; /*struct tlv*/ uint8_t msgauthinvalid; }; #define ATTRTYPE(x) ((x)[0]) #define ATTRLEN(x) ((x)[1]) #define ATTRVAL(x) ((x) + 2) #define ATTRVALLEN(x) ((x)[1] - 2) int get_checked_rad_length(uint8_t *buf); void radmsg_free(struct radmsg *); struct radmsg *radmsg_init(uint8_t, uint8_t, uint8_t *); int radmsg_add(struct radmsg *, struct tlv *, uint8_t front); struct tlv *radmsg_gettype(struct radmsg *, uint8_t); struct list *radmsg_getalltype(const struct radmsg *msg, uint8_t type); int radmsg_copy_attrs(struct radmsg *dst, const struct radmsg *src, uint8_t type); uint8_t *tlv2buf(uint8_t *p, const struct tlv *tlv); int radmsg2buf(struct radmsg *msg, uint8_t *, int, uint8_t **); struct radmsg *buf2radmsg(uint8_t *, int, uint8_t *, int, uint8_t *); uint8_t attrname2val(char *attrname); int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type); int attrvalidate(unsigned char *attrs, int length); struct tlv *makevendortlv(uint32_t vendor, struct tlv *attr); int resizeattr(struct tlv *attr, uint8_t newlen); int verifyeapformat(struct radmsg *msg); /** * convert the attribute value to its string representation form the dictionary * (see raddict.h) * * @param attr the attribute to convert * @return the string representation or NULL, if the attribute/value is not in the * dictionary */ const char *attrval2strdict(struct tlv *attr); #endif /*_RADMSG_H*/ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/fticks.c0000644000076600000240000001376414722543325011267 /* Copyright (c) 2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "fticks.h" #include "debug.h" #include "fticks_hashmac.h" #include int fticks_configure(struct options *options, uint8_t **reportingp, uint8_t **macp, uint8_t **keyp) { int r = 0; const char *reporting = (const char *)*reportingp; const char *mac = (const char *)*macp; /* Set defaults. */ options->fticks_reporting = RSP_FTICKS_REPORTING_NONE; options->fticks_mac = RSP_MAC_VENDOR_KEY_HASHED; if (reporting != NULL) { if (strcasecmp(reporting, "None") == 0) options->fticks_reporting = RSP_FTICKS_REPORTING_NONE; else if (strcasecmp(reporting, "Basic") == 0) options->fticks_reporting = RSP_FTICKS_REPORTING_BASIC; else if (strcasecmp(reporting, "Full") == 0) options->fticks_reporting = RSP_FTICKS_REPORTING_FULL; else { debugx(1, DBG_ERR, "config error: invalid FTicksReporting value: %s", reporting); r = 1; } } if (mac != NULL) { if (strcasecmp(mac, "Static") == 0) options->fticks_mac = RSP_MAC_STATIC; else if (strcasecmp(mac, "Original") == 0) options->fticks_mac = RSP_MAC_ORIGINAL; else if (strcasecmp(mac, "VendorHashed") == 0) options->fticks_mac = RSP_MAC_VENDOR_HASHED; else if (strcasecmp(mac, "VendorKeyHashed") == 0) options->fticks_mac = RSP_MAC_VENDOR_KEY_HASHED; else if (strcasecmp(mac, "FullyHashed") == 0) options->fticks_mac = RSP_MAC_FULLY_HASHED; else if (strcasecmp(mac, "FullyKeyHashed") == 0) options->fticks_mac = RSP_MAC_FULLY_KEY_HASHED; else { debugx(1, DBG_ERR, "config error: invalid FTicksMAC value: %s", mac); r = 1; } } if (*keyp != NULL) { options->fticks_key = *keyp; if (options->fticks_mac != RSP_MAC_VENDOR_KEY_HASHED && options->fticks_mac != RSP_MAC_FULLY_KEY_HASHED) debugx(1, DBG_WARN, "config warning: FTicksKey not used"); } else if (options->fticks_reporting != RSP_FTICKS_REPORTING_NONE && (options->fticks_mac == RSP_MAC_VENDOR_KEY_HASHED || options->fticks_mac == RSP_MAC_FULLY_KEY_HASHED)) { debugx(1, DBG_ERR, "config error: FTicksMAC values VendorKeyHashed and " "FullyKeyHashed require an FTicksKey"); options->fticks_reporting = RSP_FTICKS_REPORTING_NONE; r = 1; } if (*reportingp != NULL) { free(*reportingp); *reportingp = NULL; } if (*macp != NULL) { free(*macp); *macp = NULL; } return r; } void fticks_log(const struct options *options, const struct client *client, const struct radmsg *msg, const struct request *rq) { uint8_t *username = NULL; uint8_t *realm = NULL; uint8_t visinst[8 + 40 + 1 + 1]; /* Room for 40 octets of VISINST. */ uint8_t *macin = NULL; uint8_t macout[2 * 32 + 1]; /* Room for ASCII representation of SHA256. */ username = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_User_Name)); if (username != NULL) { realm = (uint8_t *)strrchr((char *)username, '@'); if (realm != NULL) realm++; } if (realm == NULL) realm = (uint8_t *)""; memset(visinst, 0, sizeof(visinst)); if (options->fticks_reporting == RSP_FTICKS_REPORTING_FULL) { if (client->conf->fticks_visinst != NULL) { snprintf((char *)visinst, sizeof(visinst), "VISINST=%s#", client->conf->fticks_visinst); } else { snprintf((char *)visinst, sizeof(visinst), "VISINST=%s#", client->conf->name); } } memset(macout, 0, sizeof(macout)); if (options->fticks_mac == RSP_MAC_STATIC) { strncpy((char *)macout, "undisclosed", sizeof(macout) - 1); } else { macin = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Calling_Station_Id)); if (macin) { switch (options->fticks_mac) { case RSP_MAC_ORIGINAL: memcpy(macout, macin, sizeof(macout)); break; case RSP_MAC_VENDOR_HASHED: memcpy(macout, macin, 9); fticks_hashmac(macin, NULL, sizeof(macout) - 9, macout + 9); break; case RSP_MAC_VENDOR_KEY_HASHED: memcpy(macout, macin, 9); /* We are hashing the first nine octets too for easier * correlation between vendor-key-hashed and * fully-key-hashed log records. This opens up for a * known plaintext attack on the key but the * consequences of that is considered outweighed by * the convenience gained. */ fticks_hashmac(macin, options->fticks_key, sizeof(macout) - 9, macout + 9); break; case RSP_MAC_FULLY_HASHED: fticks_hashmac(macin, NULL, sizeof(macout), macout); break; case RSP_MAC_FULLY_KEY_HASHED: fticks_hashmac(macin, options->fticks_key, sizeof(macout), macout); break; default: debugx(2, DBG_ERR, "invalid fticks mac configuration: %d", options->fticks_mac); } } } fticks_debug( "%s#REALM=%s#VISCOUNTRY=%s#%sCSI=%s#RESULT=%s#", options->fticksprefix, realm, client->conf->fticks_viscountry, visinst, macout, msg->code == RAD_Access_Accept ? "OK" : "FAIL"); if (macin != NULL) free(macin); if (username != NULL) free(username); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/udp.c0000644000076600000240000003307014722543325010564 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2012-2013, 2017, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include #include #include #include #include #include #include #ifdef SYS_SOLARIS #include #endif #include "hostport.h" #include "radsecproxy.h" #include #include #include #include #include #include #include #include #include #ifdef RADPROT_UDP #include "debug.h" #include "util.h" static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(void); void *udpserverrd(void *arg); int clientradputudp(struct server *server, unsigned char *rad, int radlen); void addclientudp(struct client *client); void addserverextraudp(struct clsrvconf *conf); void udpsetsrcres(void); void initextraudp(void); static const struct protodefs protodefs = { "udp", NULL, /* secretdefault */ SOCK_DGRAM, /* socktype */ "1812", /* portdefault */ REQUEST_RETRY_COUNT, /* retrycountdefault */ 10, /* retrycountmax */ REQUEST_RETRY_INTERVAL, /* retryintervaldefault */ 60, /* retryintervalmax */ DUPLICATE_INTERVAL, /* duplicateintervaldefault */ setprotoopts, /* setprotoopts */ getlistenerargs, /* getlistenerargs */ udpserverrd, /* listener */ NULL, /* connecter */ NULL, /* clientconnreader */ clientradputudp, /* clientradput */ addclientudp, /* addclient */ addserverextraudp, /* addserverextra */ udpsetsrcres, /* setsrcres */ initextraudp /* initextra */ }; struct client_sock { struct sockaddr_storage *source; int socket; }; static struct list *client_sock; static struct gqueue *server_replyq = NULL; static struct addrinfo *srcres = NULL; static uint8_t handle; static struct commonprotoopts *protoopts = NULL; const struct protodefs *udpinit(uint8_t h) { handle = h; return &protodefs; } static void setprotoopts(struct commonprotoopts *opts) { protoopts = opts; } static char **getlistenerargs(void) { return protoopts ? protoopts->listenargs : NULL; } void udpsetsrcres(void) { if (!srcres) srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, AF_UNSPEC, NULL, protodefs.socktype); } void removeudpclientfromreplyq(struct client *c) { struct list_node *n; struct request *r; /* lock the common queue and remove replies for this client */ pthread_mutex_lock(&c->replyq->mutex); for (n = list_first(c->replyq->entries); n; n = list_next(n)) { r = (struct request *)n->data; if (r->from == c) r->from = NULL; } pthread_mutex_unlock(&c->replyq->mutex); } static int addr_equal(struct sockaddr *a, struct sockaddr *b) { switch (a->sa_family) { case AF_INET: return !memcmp(&((struct sockaddr_in *)a)->sin_addr, &((struct sockaddr_in *)b)->sin_addr, sizeof(struct in_addr)) && (((struct sockaddr_in *)a)->sin_port == ((struct sockaddr_in *)b)->sin_port); case AF_INET6: return IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)a)->sin6_addr, &((struct sockaddr_in6 *)b)->sin6_addr) && (((struct sockaddr_in6 *)a)->sin6_port == ((struct sockaddr_in6 *)b)->sin6_port); default: /* Must not reach */ return 0; } } uint16_t port_get(struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: return ntohs(((struct sockaddr_in *)sa)->sin_port); case AF_INET6: return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); } return 0; } /* exactly one of client and server must be non-NULL */ /* return who we received from in *client or *server */ /* return from in sa if not NULL */ int radudpget(int s, struct client **client, struct server **server, unsigned char **buf) { int cnt, len; unsigned char init_buf[4]; struct sockaddr_storage from; struct sockaddr *fromcopy; socklen_t fromlen = sizeof(from); struct clsrvconf *p; struct list_node *node; struct client *c = NULL; struct timeval now; char tmp[INET6_ADDRSTRLEN]; for (;;) { if (*buf) { free(*buf); *buf = NULL; } cnt = recvfrom(s, init_buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen); if (cnt == -1) { debug(DBG_ERR, "radudpget: recvfrom failed - %s", strerror(errno)); continue; } p = client ? find_clconf(handle, (struct sockaddr *)&from, NULL, NULL) : find_srvconf(handle, (struct sockaddr *)&from, NULL); if (!p) { debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); sock_dgram_skip(s); continue; } len = get_checked_rad_length(init_buf); if (len <= 0) { debug(DBG_WARN, "radudpget: invalid message length: %d", -len); sock_dgram_skip(s); continue; } if (len > 4096) { debug(DBG_WARN, "radudpget: length too big"); sock_dgram_skip(s); continue; } *buf = malloc(len); if (!*buf) { debug(DBG_ERR, "radudpget: malloc failed"); sock_dgram_skip(s); continue; } cnt = recv(s, *buf, len, MSG_TRUNC); debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); if (cnt < len) { debug(DBG_WARN, "radudpget: packet smaller than length field in radius header"); continue; } if (cnt > len) debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); if (client) { *client = NULL; pthread_mutex_lock(p->lock); for (node = list_first(p->clients); node;) { c = (struct client *)node->data; node = list_next(node); if (s != c->sock) continue; gettimeofday(&now, NULL); if (!*client && addr_equal((struct sockaddr *)&from, c->addr)) { c->expiry = now.tv_sec + 60; *client = c; } if (c->expiry >= now.tv_sec) continue; debug(DBG_DBG, "radudpget: removing expired client (%s)", addr2string(c->addr, tmp, sizeof(tmp))); removeudpclientfromreplyq(c); c->replyq = NULL; /* stop removeclient() from removing common udp replyq */ removelockedclient(c); break; } if (!*client) { fromcopy = addr_copy((struct sockaddr *)&from); if (!fromcopy) { pthread_mutex_unlock(p->lock); continue; } c = addclient(p, 0); if (!c) { free(fromcopy); pthread_mutex_unlock(p->lock); continue; } c->sock = s; c->addr = fromcopy; gettimeofday(&now, NULL); c->expiry = now.tv_sec + 60; *client = c; } pthread_mutex_unlock(p->lock); } else if (server) *server = p->servers; break; } return len; } int clientradputudp(struct server *server, unsigned char *rad, int radlen) { struct clsrvconf *conf = server->conf; struct addrinfo *ai; char tmp[INET6_ADDRSTRLEN]; if (radlen <= 0) { debug(DBG_ERR, "clientradputudp: invalid buffer (length)"); return 0; } ai = ((struct hostportres *)list_first(conf->hostports)->data)->addrinfo; if (sendto(server->sock, rad, radlen, 0, ai->ai_addr, ai->ai_addrlen) >= 0) { debug(DBG_DBG, "clienradputudp: sent UDP of length %zu to %s port %d", radlen, addr2string(ai->ai_addr, tmp, sizeof(tmp)), port_get(ai->ai_addr)); return 1; } debug(DBG_WARN, "clientradputudp: send failed"); return 0; } void *udpclientrd(void *arg) { struct server *server; unsigned char *buf = NULL; int *s = (int *)arg; int len = 0; for (;;) { server = NULL; len = radudpget(*s, NULL, &server, &buf); replyh(server, buf, len); buf = NULL; } } void *udpserverrd(void *arg) { struct request *rq; int *sp = (int *)arg; for (;;) { rq = newrequest(); if (!rq) { sleep(5); /* malloc failed */ continue; } rq->buflen = radudpget(*sp, &rq->from, NULL, &rq->buf); rq->udpsock = *sp; gettimeofday(&rq->created, NULL); radsrv(rq); } free(sp); return NULL; } void *udpserverwr(void *arg) { struct gqueue *replyq = (struct gqueue *)arg; struct request *reply; struct sockaddr_storage to; for (;;) { pthread_mutex_lock(&replyq->mutex); while (!(reply = (struct request *)list_shift(replyq->entries))) { debug(DBG_DBG, "udp server writer, waiting for signal"); pthread_cond_wait(&replyq->cond, &replyq->mutex); debug(DBG_DBG, "udp server writer, got signal"); } /* do this with lock, udpserverrd may set from = NULL if from expires */ if (reply->from) memcpy(&to, reply->from->addr, SOCKADDRP_SIZE(reply->from->addr)); pthread_mutex_unlock(&replyq->mutex); if (reply->from) { if (sendto(reply->udpsock, reply->replybuf, reply->replybuflen, 0, (struct sockaddr *)&to, SOCKADDR_SIZE(to)) < 0) debug(DBG_WARN, "udpserverwr: send failed"); } debug(DBG_DBG, "udpserverwr: refcount %d", reply->refcount); freerq(reply); } } void addclientudp(struct client *client) { client->replyq = server_replyq; } void addserverextraudp(struct clsrvconf *conf) { struct addrinfo *source = NULL, *tmpaddrinfo; struct list_node *entry; char tmp[32]; assert(list_first(conf->hostports) != NULL); if (conf->source) { source = resolvepassiveaddrinfo(conf->source, AF_UNSPEC, NULL, protodefs.socktype); if (!source) debug(DBG_WARN, "addserver: could not resolve source address to bind for server %s, using default", conf->name); } if (client_sock == NULL) { client_sock = list_create(); } for (tmpaddrinfo = source ? source : srcres; tmpaddrinfo; tmpaddrinfo = tmpaddrinfo->ai_next) { if (tmpaddrinfo->ai_family == AF_UNSPEC || tmpaddrinfo->ai_family == ((struct hostportres *)list_first(conf->hostports)->data)->addrinfo->ai_family) { for (entry = list_first(client_sock); entry; entry = list_next(entry)) { if (memcmp(tmpaddrinfo->ai_addr, ((struct client_sock *)entry->data)->source, tmpaddrinfo->ai_addrlen) == 0) { conf->servers->sock = ((struct client_sock *)entry->data)->socket; debug(DBG_DBG, "addserverextraudp: reusing existing socket #%d (%s) for server %s", conf->servers->sock, addr2string(tmpaddrinfo->ai_addr, tmp, sizeof(tmp)), conf->name); break; } } if (conf->servers->sock < 0) { struct client_sock *cls = malloc(sizeof(struct client_sock)); if (!cls) debugx(1, DBG_ERR, "addserverextraudp: malloc failed"); cls->socket = bindtoaddr(tmpaddrinfo, tmpaddrinfo->ai_family, 0); cls->source = malloc(sizeof(struct sockaddr_storage)); if (!cls->source) debugx(1, DBG_ERR, "addserverextraudp: malloc failed"); memcpy(cls->source, tmpaddrinfo->ai_addr, tmpaddrinfo->ai_addrlen); debug(DBG_DBG, "addserverextraudp: creating new socket #%d (%s) for server %s", cls->socket, addr2string((struct sockaddr *)cls->source, tmp, sizeof(tmp)), conf->name); if (!list_push(client_sock, cls)) debugx(1, DBG_ERR, "addserverextraudp: malloc failed"); conf->servers->sock = cls->socket; break; } } } if (conf->servers->sock < 0) debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->name); if (source) freeaddrinfo(source); } void initextraudp(void) { pthread_t clth, srvth; struct list_node *entry; if (srcres) { freeaddrinfo(srcres); srcres = NULL; } for (entry = list_first(client_sock); entry; entry = list_next(entry)) { debug(DBG_DBG, "initextraudp: spinning up clientrd thread for socket #%d", ((struct client_sock *)entry->data)->socket); if (pthread_create(&clth, &pthread_attr, udpclientrd, (void *)&((struct client_sock *)entry->data)->socket)) debugx(1, DBG_ERR, "pthread_create failed"); } if (find_clconf_type(handle, NULL)) { server_replyq = newqueue(); if (pthread_create(&srvth, &pthread_attr, udpserverwr, (void *)server_replyq)) debugx(1, DBG_ERR, "pthread_create failed"); } } #else const struct protodefs *udpinit(uint8_t h) { return NULL; } #endif /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/radsecproxy.conf.5.in0000644000076600000240000012602514722543325013615 .TH radsecproxy.conf 5 "@RELEASEDATE@" "@PACKAGE_STRING@" "" .SH NAME radsecproxy.conf \- Radsec proxy configuration file .SH DESCRIPTION When the proxy server starts, it will first check the command line arguments, and then read the configuration file. Normally radsecproxy will read the configuration file \fI@SYSCONFDIR@/radsecproxy.conf\fR. The command line \fB\-c\fR option can be used to instead read an alternate file (see \fBradsecproxy\fR(8) for details). If the configuration file can not be found, the proxy will exit with an error message. Note that there is also an include facility so that any configuration file may include other configuration files. The proxy will also exit on configuration errors. .SH "CONFIGURATION SYNTAX" When the configuration file is processed, whitespace (spaces and tabs) are generally ignored. For each line, leading and trailing whitespace are ignored. A line is ignored if it is empty, only consists of whitespace, or if the first non-whitespace character is a #. The configuration is generally case insensitive, but in some cases the option values (see below) are not. There are two types of configuration structures than can be used. The first and simplest are lines on the format \fIoption value\fR. That is, an option name, see below for a list of valid options, followed by whitespace (at least one space or tab character), followed by a value. Note that if the value contains whitespace, then it must be quoted using "" or ''. Any whitespace in front of the option or after the value will be ignored. The other type of structure is a block. A block spans at least two lines, and has the format: .RS .nf blocktype name { option value option value ... } .fi .RE That is, some blocktype, see below for a list of the different block types, and then enclosed in braces you have zero or more lines that each have the previously described \fIoption value\fR format. Different block types have different rules for which options can be specified, they are listed below. The rules regarding white space, comments and quotes are as above. Hence you may do things like: .RS .nf blocktype name { # option value option "value with space" ... } .fi .RE Option value characters can also be written in hex for options requiring a string type value. A % character followed by two hexadecimal digits will be replaced by its byte value. Longer hex strings can be escaped with %%. In this case all following hexadecimal digit pairs will be replace by byte values until the first non-hex character. If a % is used without two following hexadecimal digits, the % and the following characters are used as written. If you want to write a % and not use this decoding, you may of course write % in hex; i.e., %25. As %00 would terminate a string, this value is not converted in most cases, except when used with rewrite statements or secrets. Some options allow or require the use of regular expressions, denoted as \fIregex\fR. The POSIX extended RE system is used, see .BR re_format (7). There is one special option that can be used both as a basic option and inside all blocks. That is the option \fIInclude\fR where the value specifies files to be included. The value can be a single file, or it can use normal shell globbing to specify multiple files, e.g.: .RS include @SYSCONFDIR@/radsecproxy.conf.d/*.conf .RE The files are sorted alphabetically. Included files are read in the order they are specified, when reaching the end of a file, the next file is read. When reaching the end of the last included file, the proxy returns to read the next line following the \fIInclude\fR option. Included files may again include other files. .SH "BASIC OPTIONS" The following basic options may be specified in the configuration file. Note that blocktypes and options inside blocks are discussed later. Note that none of these options are required, and indeed in many cases they are not needed. Note that you should specify each at most once. The behaviour with multiple occurrences is undefined. .BI "PidFile " file .RS The PidFile option specifies the name of a \fIfile\fR to which the process id (PID) will be written. This is overridden by the \fB\-i\fR command line option. There is no default value for the PidFile option. .RE .BR "LogLevel " "1-5" .RS This option specifies the debug level. It must be set to 1, 2, 3, 4 or 5, where 1 logs only serious errors, and 5 logs everything. The default is 2 which logs errors, warnings and a few informational messages. Note that the command line option \fB\-d\fR overrides this. .RE .BI "LogDestination (" file | syslog ) .RS This specifies where the log messages should go. By default the messages go to syslog with facility \fBLOG_DAEMON\fR. Using this option you can specify another syslog facility, or you may specify that logging should be to a particular file, not using syslog. The value must be either a file URL like \fBfile:///path/to/your/logfile.log\fR or a syslog URL using the syntax: .BR "x\-syslog:///FACILITY" " where " FACILITY " must be one of " .BR LOG_DAEMON , .BR LOG_MAIL , .BR LOG_USER , .BR LOG_LOCAL0 , .BR LOG_LOCAL1 , .BR LOG_LOCAL2 , .BR LOG_LOCAL3 , .BR LOG_LOCAL4 , .BR LOG_LOCAL5 , .BR LOG_LOCAL6 or .BR LOG_LOCAL7 . You may omit the facility from the URL to specify logging to the default facility, but this is not very useful since this is the default log destination. Note that this option is ignored if \fB\-f\fR is specified on the command line. .RE .BR "LogThreadId (" on | off ) .RS This can be set to on to include the thread-id in the log messages (useful for debugging). .RE .BR "LogFullUsername (" on | off ) .RS This can be set to off to only log the realm in Access-Accept/Reject log messages (for privacy). .RE .BI "LogMAC " opt .RS The LogMAC option can be used to control if and how Calling-Station-Id (the users Ethernet MAC address) is being logged. It can be set to one of .BR Static , .BR Original , .BR VendorHashed , .BR VendorKeyHashed , .BR FullyHashed or .BR FullyKeyHashed . The default value for LogMAC is \fBOriginal\fR. See \fIradsecproxy.conf\-example\fR for details. .RE .BI "LogKey " key .RS The LogKey option is used to specify the \fIkey\fR to use when producing HMAC's as an effect of specifying \fBVendorKeyHashed\fR or \fBFullyKeyHashed\fR for the LogMAC option. .RE .BI "FTicksReporting " fticks .RS The FTicksReporting option is used to enable F-Ticks logging and can be set to .BR None , .BR Basic or .BR Full. Its default value is \fBNone\fR. If FTicksReporting is set to anything other than \fBNone\fR, note that the default value for \fBFTicksMAC\fR needs \fBFTicksKey\fR to be set. See \fIradsecproxy.conf\-example\fR for details. .RE .BI "FTicksMAC " opt .RS The FTicksMAC option has the same function as LogMAC for FTicks. The default for FTicksMAC is \fBVendorKeyHashed\fR which needs \fBFTicksKey\fR to be set. Before choosing any of .BR Original , .BR FullyHashed or .BR VendorHashed , consider the implications for user privacy when MAC addresses are collected. How will the logs be stored, transferred and accessed? .RE .BI "FTicksKey " key .RS The FTicksKey option has the same function as LogKey for Fticks. .RE .BI "FTicksSyslogFacility " syslog .RS The FTicksSyslogFacility option is used to specify a dedicated syslog facility for F-Ticks messages. This allows for easier filtering of F-Ticks messages. If no FTicksSyslogFacility option is given, F-Ticks messages are written to what the \fBLogDestination\fR option specifies. F-Ticks messages are always logged using the log level \fBLOG_DEBUG\fR. Note that specifying a file in FTicksSyslogFacility (using the file:/// prefix) is not supported. .RE .BI "FTicksPrefix " prefix .RS The FTicksPrefix option is used to set the \fIprefix\fR printed in F-Ticks messages. This allows for use of F-Ticks messages in non-eduroam environments. If no FTicksPrefix option is given, it defaults to the prefix used for eduroam (\fIF\-TICKS/eduroam/1.0\fR). .RE .BI "ListenUDP (" address | \fR* )[\fR: port ] .br .BI "ListenTCP (" address | \fR* )[\fR: port ] .br .BI "ListenTLS (" address | \fR* )[\fR: port ] .br .BI "ListenDTLS (" address | \fR* )[\fR: port ] .RS Listen for the address and port for the respective protocol. Normally the proxy will listen to the standard ports if configured to handle clients with the respective protocol. The default ports are 1812 for \fBUDP\fR and \fBTCP\fR and 2083 for \fBTLS\fR and \fBDTLS\fR. On most systems it will do this for all of the system's IP addresses (both IPv4 and IPv6). On some systems however, it may respond to only IPv4 or only IPv6. To specify an alternate port you may use a value on the form *:\fIport\fR where \fIport\fR is any valid port number. If you also want to specify a specific \fIaddress\fR you can do e.g. 192.168.1.1:1812 or [2001:db8::1]:1812. The port may be omitted if you want the default one. Note that you must use brackets around the IPv6 address. These options may be specified multiple times to listen to multiple addresses and/or ports for each protocol. .RE .BI "SourceUDP (" address | \fR* )[\fR: port ] .br .BI "SourceTCP (" address | \fR* )[\fR: port ] .br .BI "SourceTLS (" address | \fR* )[\fR: port ] .br .BI "SourceDTLS (" address | \fR* )[\fR: port ] .RS This can be used to specify source address and/or source port that the proxy will use for connecting to clients to send messages (e.g. Access Request). The same syntax as for \fBListen...\fR applies. .RE .BI "TTLAttribute (" attr | vendor : attr ) .RS This can be used to change the default TTL attribute. Only change this if you know what you are doing. The syntax is either a numerical value denoting the TTL attribute, or two numerical values separated by column specifying a vendor attribute. .RE .BR "AddTTL " "1-255" .RS If a TTL attribute is present, the proxy will decrement the value and discard the message if zero. Normally the proxy does nothing if no TTL attribute is present. If you use the AddTTL option with a value 1-255, the proxy will, when forwarding a message with no TTL attribute, add one with the specified value. Note that this option can also be specified for a client/server which will override this setting when forwarding a message to that client/server. .RE .BR "LoopPrevention (" on | off ) .RS When this is enabled (on), a request will never be sent to a server named the same as the client it was received from. I.e., the names of the client block and the server block are compared. Note that this only gives limited protection against loops. It can be used as a basic option and inside server blocks where it overrides the basic setting. .RE .BR "IPv4Only (" on | off ) .br .BR "IPv6Only (" on | off ) .RS Enabling IPv4Only or IPv6Only (on) makes radsecproxy resolve DNS names to the corresponding address family only, and not the other. This is done for both clients and servers. At most one of IPv4Only and IPv6Only can be enabled. Note that this can be overridden in client and server blocks, see below. .RE .BR "SNI (" on | off ) .RS Server Name Indication (SNI) is an extension to the TLS protocol. It allows a client to indicate which hostname it is trying to connect to at the start of the TLS handshake. Enabling this will use the extension for all TLS and DTLS servers which specify a hostname (not IP address). This can be overridden in server blocks, see below. .RE .BR "VerifyEAP (" on | off ) .RS A radius proxy is mostly agnostic to the contents of the attributes within a radius message and forwards them as-is. However wrong EAP attributes can lead to bad user experience. Thus radsecproxy checks the content length of the contained EAP message and denies the access-request if it doesn't match the attribute length. In case malformatted EAP attributes are inentional, this behaviour can be disabled (default on). .RE .BI "Include " file .RS This is not a normal configuration option; it can be specified multiple times. It can both be used as a basic option and inside blocks. For the full description, see the configuration syntax section above. .RE .SH BLOCKS There are five types of blocks, they are .BR client , .BR server , .BR realm , .BR tls and .BR rewrite . At least one instance of each of \fBclient\fR and \fBrealm\fR is required for the proxy to do anything useful, and it will exit if none are configured. The \fBtls\fR block is required if at least one TLS/DTLS client or server is configured. Note that there can be multiple blocks for each type. For each type, the block names should be unique. The behaviour with multiple occurrences of the same name for the same block type is undefined. Also note that some block option values may reference a block by name, in which case the block name must be previously defined. Hence the order of the blocks may be significant. .SH "CLIENT BLOCK" .nf .BI "client (" name | fqdn |( address [/ length ])) "\fR {" ... } .fi .PP The client block is used to configure a client. That is, tell the proxy about a client, and what parameters should be used for that client. The name of the client block must (with one exception, see below) be either the IP \fIaddress\fR (IPv4 or IPv6) of the client, an IP prefix (IPv4 or IPv6) on the form IpAddress/PrefixLength, or a domain name (\fIFQDN\fR). The way an FQDN is resolved into an IP address may be influenced by the use of the \fBIPv4Only\fR and \fBIPv6Only\fR options. Note that literal IPv6 addresses must be enclosed in brackets. If a domain name is specified, then this will be resolved immediately to all the addresses associated with the name, and the proxy will not care about any possible DNS changes that might occur later. Hence there is no dependency on DNS after startup. However, if the name can not be resolved, startup will fail. When some client later sends a request to the proxy, the proxy will look at the IP address the request comes from, and then go through all the addresses of each of the configured clients (in the order they are defined), to determine which (if any) of the clients this is. When using the IpAddress/PrefixLength form, this might mask clients defined later, which then will never be matched. In the case of TLS/DTLS, the name of the client must match the FQDN or IP address in the client certificate (CN or SubectAltName:DNS or SubjectAltName:IP respectively) and any \fBMatchCertificateAttribute\fR to be positively identified. Note that no FQDN/IP is checked when using an IP prefix. If overlapping clients are defined (see section above), they will be searched for positive identification, but only among clients referencing the same tls block (selected by the first matching IP address or prefix). The allowed options in a client block are: .BI "Host (" fqdn |( address [/ length ])) .RS Alternatively of specifying the FQDN or address in the block name, the \fBhost\fR option may be used. In that case, the value of the \fBhost\fR option is used as described above, while the name of the block is only used as a descriptive name for the administrator. The host option may be used multiple times, and can be a mix of addresses, FQDNs and prefixes. .RE .BR "IPv4Only (" on | off ) .br .BR "IPv6Only (" on | off ) .RS Enabling IPv4Only or IPv6Only (on) makes radsecproxy resolve DNS names to the corresponding address family only, and not the other. At most one of IPv4Only and IPv6Only can be enabled. Note that this will override the global option for this client. .RE .BI "Type " type .RS Specify the \fItype\fR (protocol) of the client. Available options are .BR UDP , .BR TCP , .BR TLS and .BR DTLS . .br While TLS and DTLS are secure, enctrypted transports, UDP and TCP are not. Radius uses the shared secret only to encrypt certain critical attributes, but most of the Radius data is sent in clear. Protection against manipulation is only provided if the client uses the Message-Authenticator attribute. .br Therefore UDP and TCP should only be used in secured networks or when an underying secure transport such as IPSEC or MACSEC is used. UDP and TCP SHOULD NOT be used across the internet. .RE .BI "Secret " secret .RS Use \fIsecret\fR as the shared RADIUS key with this client. If the secret contains whitespace, the value must be quoted. This option is optional for TLS/DTLS and if omitted will default to "radsec". (Note that using a secret other than "radsec" for TLS is a violation of the standard (RFC 6614) and that the proposed standard for DTLS stipulates that the secret must be "radius/dtls".) .RE .BI "TLS " tls .RS For a TLS/DTLS client you may also specify the \fBtls\fR option. The option value must be the name of a previously defined TLS block. If this option is not specified, the TLS block with the name \fBdefaultClient\fR or \fBdefault\fR will be used if defined (in that order). If the specified TLS block name does not exist, or the option is not specified and none of the defaults exist, the proxy will exit with an error. .RE .BI "ServerName " servername .RS Use \fIservername\fR for the certificate name check instead of \fBhost\fR or the client block name (e.g. if \fBhost\fR uses static IP address). .RE .BR "CertificateNameCheck (" on | off ) .RS For a TLS/DTLS client, disable the default behaviour of matching CN or SubjectAltName against the specified hostname or IP address. .RE \fBMatchCertificateAttribute \fRCN:/\fIregexp\fR/ .br \fBMatchCertificateAttribute \fRSubjectAltName:DNS:/\fIregexp\fR/ .br \fBMatchCertificateAttribute \fRSubjectAltName:URI:/\fIregexp\fR/ .br \fBMatchCertificateAttribute \fRSubjectAltName:IP:\fIaddress\fR .br \fBMatchCertificateAttribute \fRSubjectAltName:rID:\fIoid\fR .br \fBMatchCertificateAttribute \fRSubjectAltName:otherName:\fIoid\fR:/\fIregexp\fR/ .RS Perform additional validation of certificate attributes. Currently matching of CN and SubjectAltName types URI, DNS, IP, rID, and otherName is supported. If specified multiple times, all terms must match for the certificate to be considered valid. .RE .BI "PSKkey " key .RS For TLS, use TLS-PSK (pre shared key) instead of certificate based authentication. If specified, \fBPSKidentity\fR must also be provided. The \fIkey\fR must be at least 16 bytes long. To provide the \fIkey\fR in hex, use the %% escaping (see CONFIGURATION SYNTAX). In addition to the psk, peers must also agree on the key derivation hash function. For this, the server simply uses the hash funciton of the negotiated cipher as this negotiation must yield a compatible cipher anyway. To ensure unambiguous cipher and hash selection, only use ciphers with the same hash function in the \fBCipherSuites\fR of the \fBtls\fR block. If no \fBtls\fR block is specified, a default config with SHA256 is used. Note: only TLS1.3 PSK is supported and only for TLS, not DTLS (pending OpenSSL DTLS1.3 support). .RE .BI "PSKidentity " identity .RS The TLS-PSK \fIidentity\fR to identify the client. When omitted, the \fBclient \fIname\fR is used as the identity. When using TLS-PSK, all clients are identified by thier PSK identity, however it is highly recommended to limit the allowed source address(es) using the \fBHost \fIaddress\fR option. .RE .BI "DuplicateInterval " seconds .RS Specify for how many \fIseconds\fR duplicate checking should be done. If a proxy receives a new request within a few seconds of a previous one, it may be treated the same if from the same client, with the same authenticator etc. The proxy will then ignore the new request (if it is still processing the previous one), or returned a copy of the previous reply. .RE .BR "AddTTL " 1-255 .RS The AddTTL option has the same meaning as the option used in the basic config. See the \fBBASIC OPTIONS\fR section for details. Any value configured here overrides the basic one when sending messages to this client. .RE .BR "TCPKeepalive (" on | off ) .RS Enable TCP keepalive (default is off). If keepalives are not answered within 30s the connection is considered lost. .RE .BI "FticksVISCOUNTRY " cc .RS Sets this client to be eligible to F-Ticks logging as defined by the \fBFTicksReporting\fR basic option, and specifies the country to be reported. The country should be specified by the two-letter country code. .RE .BI "FticksVISINST " institution .RS Set the institution to report in F-Ticks logging. If this option is omitted, the name of the client block is used. .RE .BI "Rewrite " rewrite .RS This option is deprecated. Use \fBrewriteIn\fR instead. .RE .BI "RewriteIn " rewrite .br .BI "RewriteOut " rewrite .RS Apply the operations in the specified \fIrewrite\fR block on incoming (request) or outgoing (response) messages from this client. Rewriting incoming messages is done before, outgoing after other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultClient\fR or \fBdefault\fR will be applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BI "RewriteAttribute User-Name:/" regex / replace / .RS Rewrite the User-Name attribute in a client request for the request forwarded by the proxy. The User-Name attribute is written back to the original value if a matching response is later sent back to the client. Example usage: RewriteAttribute User-Name:/^(.*)@local$/\e1@example.com/ .RE .BR "RequireMessageAuthenticator (" on | off ) .RS Require all Access-Requests be signed with a Message-Authenticator. .br This should be enabled if the client is a proxy, or a NAS known to use Message-Authenticator (e.g. all EAP based NAS like Wifi). .br This setting is ignored when using TLS/DTLS transport. .RE .BR "RequireMessageAuthenticatorProxy (" on | off) .RS Require all Access-Requests containing a Proxy-State attribute to be signed with a Message-Authenticaor. .br This should always be enabled if the client is a NAS. .br This setting is ignored when using TLS/DLTS transport or when \fB RequireMessageAuthenticator\fR is enabled. .RE .SH "SERVER BLOCK" .nf .BI "server (" name |(( fqdn | address )[\fR: port ])) "\fR {" ... } .fi .PP The server block is used to configure a server. That is, tell the proxy about a server, and what parameters should be used when communicating with that server. The name of the server block must (with one exception, see below) be either the IP address (IPv4 or IPv6) of the server, or a domain name (FQDN). If a domain name is specified, then this will be resolved immediately to all the addresses associated with the name, and the proxy will not care about any possible DNS changes that might occur later. Hence there is no dependency on DNS after startup. If the domain name resolves to multiple addresses, then for UDP/DTLS the first address is used. For TCP/TLS, the proxy will loop through the addresses until it can connect to one of them. The way an FQDN is resolved into an IP address may be influenced by the use of the \fBIPv4Only\fR and \fBIPv6Only\fR options. In the case of TLS/DTLS, the name of the server must match the FQDN or IP address in the server certificate. Note that the \fIfqdn\fR or \fIaddress\fR may include a \fIport\fR number (separated with a column). This port number will then override the default port or a port option in the server block. Also note that literal IPv6 addresses must be enclosed in brackets. The allowed options in a server block are: .BI "Host (" fqdn | address )[\fR: port ] .RS Alternatively of specifying the FQDN or address in the block name the \fBhost\fR option may be used. In that case, the value of the \fBhost\fR option is used as described above, while the name of the block is only used as a descriptive name for the administrator. Note that multiple host options may be used. This will then be treated as multiple names/addresses for the same server. When initiating a TCP/TLS connection, all addresses of all names may be attempted, but there is no failover between the different host values. For failover use separate server blocks. .RE .BI "Port " port .RS Specify the \fIport\fR (UDP/TCP) to connect to. If omitted, UDP and TCP will default to 1812 while TLS and DTLS will default to 2083. .RE .BI "Source (" address | \fR* )[\fR: port ] .RS Specify the source address and/or port to use for this server. See \fBSource...\fR options above. .RE .BI "DynamicLookupCommand " command .RS Execute the \fIcommand\fR to dynamically configure a server for a realm given by the username field in an Access-Request. The command can take two special forms, naptr:\fIservice\fR or srv:\fIprefix\fR, or point to a script or executable. The \fBnaptr:\fR and \fBsrv:\fR forms execute the corresponding DNS queries, either searching for \fIservice\fR in NAPTR records (followed by SRV query), or querying for \fIprefix\fB.realm\fR SRV records. Finally a server block will be constructed for the dynamic realm taking this server block as a template and overriding the \fBhost\fR entries with the content of the SRV records. Otherwise, the \fIcommand\fR should be an executable file or script, given with full path, that will be invoked with the name of the realm as its first and only argument. It should either print a valid \fBserver {...}\fR block containing at least one \fBhost\fR statement on stdout and exit with a code of 0, or print nothing and exit with a non-zero exit code. If the command exited with 0 and provided a valid server config, it will be combined with the statements in this server block, with the values returned by the command taking preference. An example of a shell script resolving the DNS NAPTR records for the realm and then the SRV records for each NAPTR matching \&'x-eduroam:radius.tls' is provided in \fItools/naptr\-eduroam.sh\fR. This is equivalent to configuring 'naptr:x-eduroam:radius.tls' directly. .RE .BI "ServerName " servername .RS Use \fIservername\fR for the certificate name check instead of \fBhost\fR or the server block name (e.g. if \fBhost\fR uses static IP address). Additionally, this name is used for SNI (if enabled), unless \fBSNIservername\fR is set. .RE .BR "SNI (" on | off ) .RS Override gobal SNI setting (see above). This is implicitly enabled if \fBSNIservername\fR is set. .RE .BI "SNIservername " sni .RS Explicitly set the \fIsni\fR to request from the server, in case the server is specified by IP address or to override the hostname. Implicitly enables \fBSNI\fR for this server. .RE .BI "PSKkey " key .br .BI "PSKidentity " identity .RS The meaning of these options are very similar as for the client block, with minor differences. .br - The \fIidentity\fR must always be provided and cannot be derived from the \fBserver \fIname\fR. .br - For the key derivation hash funciton, the hash function of the first cipher in the \fBCipherSuites\fR of the referenced \fBtls\fR block is used. .RE .BR "StatusServer (" on | off | minimal | auto ) .RS Enable the use of status-server messages for this server (default \fBoff\fR). If statusserver is enabled (\fBon\fR), the proxy will send regular status-server messages to the server to verify that it is alive. Status tracking of the server will solely depend on status-server message and ignore lost requests. This should only be enabled if the server supports it. With the option \fBminimal\fR status-server messages are only sent when regular requests have been lost and no other replies have been received. The option \fBauto\fR tries to detect whether the other server supports status-server. If so, status-server messages are enabled in \fBminimal\fR mode. .RE .BI "RetryCount " count .RS Set how many times the proxy should retry sending a request to the server. Default is 2 retries for UDP and DTLS. For TCP and TLS it is always 0. .br Retries from radius clients are ignored and radsecproxy performs its own retry handling since the requiremets differ when switching transport protocols. .RE .BI "RetryInterfval " interval .RS Set the interval between each retry. Default is 5s. .RE .BI "Rewrite " rewrite .RS This option is deprecated. Use \fBrewriteIn\fR instead. .RE .BI "RewriteOut " rewrite .br .BI "RewriteIn " rewrite .RS Apply the operations in the specified \fIrewrite\fR block on outgoing (request) or incoming (response) messages to/from this server. Rewriting outgoing messages is done after, incoming before other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultServer\fR or \fBdefault\fR will be applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BR "LoopPrevention (" on | off) .RS This overrides the global \fBLoopPrevention\fR option for this server. See section \fBBASIC OPTIONS\fR for details on this option. .RE .BR "BlockingStartup (" on | off) .RS Start the dynamic server in blocking mode (default off), treating it as if it was already connected and enqueue requests to this server. Queued requests will be sent out when the connection is established. If however the dynamic lookup or the connection fails, the queued requests will be lost. (This is only considered for dynamic lookup servers. Ie when DynamicLookupCommand is specified) Warning: when the dynamic lookup and connection process is slow, this wil block the respective realm for that time. .RE .BI "DTLSForceMTU " mtu .RS Some non-Linux platforms are unable to query the MTU of a connection, causing DTLS to limit itself to 256 bytes and thus failing to connect. Manually set \fImtu\fR to a large enough value so the initial DTLS client-hello fits without fragmentation. .RE .BR "RequireMessageAuthenticator (" on | off ) .RS Require all responses to Access-Requests be signed with a Message-Authenticator. .br This should always be be enabled unless the server is known to only support legacy RADIUS/UDP behavior. .br This setting is ignored when using TLS/DTLS transport. .RE The meaning and syntax of the following options are exactly the same as for the client block. The details are not repeated here. Please refer to the definitions in the \fBCLIENT BLOCK\fR section. .BR "IPv4Only (" on | off ) .br .BR "IPv6Only (" on | off ) .br .BI "Type " type .br .BI "Secret " secret .br .BI "TLS " tls .br .BR "CertificateNameCheck (" on | off ) .br \fBMatchCertificateAttribute \fR... .br .BR "AddTTL " 1-255 .br .BR "TCPKeepalive (" on | off ) .SH "REALM BLOCK" .nf .BI "realm (" \fR* | realm |\fR/ regex\fR/ ) "\fR {" ... } .fi .PP When the proxy receives an Access-Request it needs to figure out to which server it should be forwarded. This is done by looking at the Username attribute in the request, and matching that against the names of the defined realm blocks. The proxy will match against the blocks in the order they are specified, using the first match if any. If no realm matches, the proxy will simply ignore the request. Each realm block specifies what the server should do when a match is found. The allowed options in a realm block are: .BI "Server " server .br .BI "AccountingServer " server .RS Specify the \fIserver\fR to which requests for this realm should be forwarded. \fIserver\fR references a previously defined \fBserver\fR block (see the \fBSERVER BLOCK\fR section). Each \fBserver\fR and \fBaccountingServer\fR can be specified multiple times, or omitted completely. If no \fBserver\fR is configured, the proxy will deny all Access-Requests for this realm. If no \fBaccountingServer\fR is configured, the proxy will silently ignore all Accounting-Requests for this realm. See the \fBSERVER SELECTION\fR section below for details. .RE .BR "AccountingResponse (" on | off ) .RS Enable sending Accounting-Response instead of ignoring Accounting-Requests when no \fBaccoutingServer\fR are configured. .RE .BR "AccountingLog (" on | off ) .RS When responding to Accounting-Requests (\fBAccountingResponse on\fR), log the accounting data. .RE .BI "ReplyMessage " message .RS Specify a message to be sent back to the client if a Access-Request is denied because no \fBserver\fR are configured. .RE .SS "REALM BLOCK NAMES AND MATCHING" In the general case the proxy will look for a \fB@\fR in the username attribute, and try to do an exact, case insensitive match between what comes after the @ and the name of the realm block. So if you get a request with the attribute value anonymous@example.com, the proxy will go through the realm names in the order they are specified, looking for a realm block named example.com. There are two exceptions to this, one is the realm name \fB*\fR which means match everything. Hence if you have a realm block named *, then it will always match. This should then be the last realm block defined, since any blocks after this would never be checked. This is useful for having a default. The other exception is regular expression matching. If the realm name starts with a \fB/\fR, the name is treated as an regular expression. A case insensitive regexp match will then be done using this regexp on the value of the entire Username attribute. Optionally you may also have a trailing / after the regexp. So as an example, if you want to use regexp matching the domain example.com you could have a realm block named /@example\e.com$/. If you want to match all domains under the \.com top domain, you could do /@.*\e.com$/. Note that since the matching is done on the entire attribute value, you can also use rules like /^[a\-k].*@example\e.com$/ to get some of the users in this domain to use one server, while other users could be matched by another realm block and use another server. .SS "SERVER SELECTION" Normally requests will be forwarded to the first server option defined. If there are multiple server options, the proxy will do fail-over and use the second server if the first is down. If the two first are down, it will try the third etc. If the first server comes back up, it will go back to using that one. Detection of servers being up or down is based on the use of StatusServer (if enabled), and that TCP/TLS/DTLS connections are up. Otherwise unanswered requests are used to detect unresponsive servers. AccountingServers are treated the same, but independently of the other servers. If there is no \fBServer\fR option (or all dynamic lookups have failed), the proxy will if \fBReplyMessage\fR is specified, reply back to the client with an Access Reject message. The message contains a replyMessage attribute with the value as specified by the \fBReplyMessage\fR option. Note that this is different from having no match since then the request is simply ignored. This can be used to catch all undefined sub-domains or even all undefined realms by configuring either a regex match like /@.*\e.example\e.com/ or the realm \fB*\fR with no server option. Another use-case is to block a specific pattern in the username or realm part using a regex. If there is no \fBAccountingServer\fR option, the proxy will normally do nothing, ignoring accounting requests. If instead \fBAccountingResponse\fR is set to on, the proxy will log some of the accounting information and send an Accounting-Response back. This stops clients from retransmitting Accounting-Request messages when a realm has no accountingServer configured. .SH "TLS BLOCK" .nf .BI "tls " name "\fR {" ... } .fi .PP The TLS block specifies TLS configuration options and you need at least one of these if you have clients or servers using TLS/DTLS. As discussed in the client and server block descriptions, a client or server block may reference a particular TLS block by name. There are also however the special TLS block names \fBdefault\fR, \fBdefaultClient\fR and \fBdefaultServer\fR which are used as defaults if the client or server block does not reference a TLS block. Also note that a TLS block must be defined before the client or server block that would use it. If you want the same TLS configuration for all TLS/DTLS clients and servers, you need just a single tls block named \fBdefault\fR, and the client and servers need not refer to it. If you want all TLS/DTLS clients to use one config, and all TLS/DTLS servers to use another, then you would be fine only defining two TLS blocks named \fBdefaultClient\fR and \fBdefaultServer\fR. If you want different clients (or different servers) to have different TLS parameters, then you may need to create other TLS blocks with other names, and reference those from the client or server definitions. As both clients and servers need to present and verify a certificate, both a certificate as well as a CA to verify the peers certificate must be configured. The allowed options in a tls block are: .BI "CACertificateFile " file .RS The CA certificate file used to verify the peers certificate. The \fIfile\fR can include multiple certificates as well as CRLs. .RE .BI "CACertificatePath " path .RS The path to search for CA or intermediate certificates and CRLs. All files must have hashed symbolic links to be found. See .BR openssl-rehash (1). .RE .BI "CertificateFile " file .RS The server certificate this proxy will use. The file may also contain a certificate chain. Any missing certificates to complete the chain will be searched for in the \fBCACertificateFile\fR and \fBCACertificatePath\fR. .RE .BI "CertificateKeyFile " file .RS The private-key file for the server certificate specified in \fBCACertificateFile\fR. .RE .BI "CertificateKeyPassword " password .RS The password to decrypt the private-key. .RE .BI "PolicyOID " oid .RS Require the peers certificate to adhere to the policy specified by \fIoid\fR. When specified multiple times at least one policy must be valid in the peer certificate. .RE .BR "CRLCheck (" on | off ) .RS Enable checking peer certificate against the CRL (default off). Note if enabled, all CAs in this context MUST provide a CRL, otherwise they are considered untrusted. .br Note that radsecproxy does not fetch the CRLs itself. This has to be done separately, e.g. with .BR fetch-crl (8) .RE .BI "CacheExpiry " seconds .RS Specify how many \fIseconds\fR the CA and CRL information should be cached. By default, the CA and CRL are loaded at startup and cached indefinetely. After the configured time, the CA and CRL are re-read. Alternatively, reloading the CA and CRL can be triggered by sending a SIGHUP to the radsecproxy process. This option may be set to zero to disable caching, but be warned: this might have a huge performance impact. .br Any negative value will disable the cache expiry. .RE .BI "CipherList " ciphers .RS Specify the list of accepted \fIciphers\fR. See .BR openssl-ciphers (1). .RE .BI "CipherSuites " ciphersuites .RS Specify the \fIciphersuites\fR to be used for TLS1.3. See .BR openssl-ciphers (1). .br Note this requires OpenSSL 1.1.1 .RE .BR "TlsVersion " ( .IR version " | " minversion : maxversion " )" .br .BR "DtlsVersion " ( .IR version " | " minversion : maxversion " )" .RS Specify the TLS/DTLS protocol \fIversion\fR to be used. .br Specify the range of allowed protocol versions between \fIminversion\fR and \fImaxversion\fR (inclusive). If either is left out, any version up to, or starting from this version is allowed. E.g. "TLS1_2:" will allow TLSv1.2 or later. If omitted, use the system defaults set in openssl.conf .br Currently supported values are .BR SSL3 , TLS1 , TLS1_1 , TLS1_2 , TLS1_3 for TLS and .BR DTLS1 , DTLS1_2 for DTLS. .RE .BI "DhFile " file .RS DH parameter \fIfile\fR to use. See \fBopenssl-dhparam\fR(1) .br Note: starting with OpenSSL 3.0, use of custom DH parameters is discouraged. .SH "REWRITE BLOCK" .nf .BI "rewrite " name "\fR {" ... } .fi .PP The rewrite block specifies rules that may rewrite RADIUS messages. It can be used to add, remove and modify specific attributes from messages received from and sent to clients and servers. As discussed in the client and server block descriptions, a client or server block may reference a particular rewrite block by name. There are however also the special rewrite block names \fBdefault\fR, \fBdefaultClient\fR and \fBdefaultServer\fR which are used as defaults if the client or server block does not reference a block. Also note that a rewrite block must be defined before the client or server block that would use it. If you want the same rewrite rules for input from all clients and servers, you need just a single rewrite block named \fBdefault\fR, and the client and servers need not refer to it. If you want all clients to use one config, and all servers to use another, then you would be fine only defining two rewrite blocks named \fBdefaultClient\fR and \fBdefaultServer\fR. Note that these defaults are only used for rewrite on input. No rewriting is done on output unless explicitly specified using the \fBRewriteOut\fR option. The rewrite actions are performed in this sequence: .RS 1. RemoveAttribute (or WhitelistAttribute) .br 2. ModifyAttribute .br 3. SupplementAttribute .br 4. AddAttribute .RE All options can be specified multiple times. The allowed options in a rewrite block are: .BI "AddAttribute " attribute \fR: value .RS Add an \fIattribute\fR to the radius message and set it to \fIvalue\fR. The \fIattribute\fR must be specified using the numerical attribute id. The \fIvalue\fR can either be numerical, a string, or a hex value. If the value starts with a number, it is interpreted as a 32bit unsigned integer. Use the ' character at the start of the value to force string interpretation. When using hex value, it is recommended to also lead with ' to avoid unintended numeric interpretation. See the \fBCONFIGURATION SYNTAX\fR section for further details. .RE .BI "AddVendorAttribute " vendor \fR: subattribute \fR: value .RS Add a vendor attribute to the radius message, specified by \fIvendor\fR and \fIsubattribute\fR. Both \fIvendor\fR and \fIsubattribute\fR must be specified as numerical values. The format of \fIvalue\fR is the same as for \fBaddAttribute\fR above. .RE .BI "SupplementAttribute " attribute \fR: value .RS Add an \fIattribute\fR to the radius message and set it to \fIvalue\fR, only if the attribute is not yet present on the message. The format of \fIvalue\fR is the same as for \fBaddAttribute\fR above. .RE .BI "SupplementVendorAttribute " vendor \fR: subattribute \fR: value .RS Add a vendor attribute to the radius message only if the \fIsubattribute\fR of this \fIvendor\fR is not yet present on the message. The format of is the same as for \fBaddVendorAttribute\fR above. .RE .BI "ModifyAttribute " attribute \fR:/ regex \fR/ replace \fR/ .RS Modify the given \fIattribute\fR using the \fIregex\fR \fIreplace\fR pattern. As above, \fIattribute\fR must be specified by a numerical value. Example usage: modifyAttribute 1:/^(.*)@local$/\e1@example.com/ .RE .BI "ModifyVendorAttribute " vendor \fR: subattribute \fR:/ regex \fR/ replace \fR/ .RS Modify the given \fIsubattribute\fR of given \fIvendor\fR using the \fIregex\fR \fIreplace\fR pattern. Other than the added vendor, the same syntax as for \fBModifyAttribute\fR applies. .RE .BI "RemoveAttribute " attribute .RS Remove all attributes with the given id. .RE .BI "RemoveVendorAttribute " vendor [\fR: subattribute ] .RS Remove all vendor attributes that match the given \fIvendor\fR and \fIsubattribute\fR. If the \fIsubattribute\fR is omitted, all attributes with the given vendor id are removed. .RE .BR "WhitelistMode (" on | off ) .RS Enable whitelist mode. All attributes except those configured with \fBWhitelistAttribute\fR or \fBWhitelistVendorAttribute\fR will be removed. While whitelist mode is active, \fBRemoveAttribute\fR and \fBRemoveVendorAttribute\fR statements are ignored. .RE .BI "WhitelistAttribute " attribute .RS Do not remove attributes with the given id when \fBWhitelistMode\fR is on. Ignored otherwise. .RE .BI "WhitelistVendorAttribute " vendor [\fR: subattribute ] .RS Do not remove vendor attributes that match the given \fIvendor\fR and \fIsubattribute\fR when \fBWhitelistMode\fR is on. Ignored otherwise. If the \fIsubattribute\fR is omitted, the complete vendor attribute is whitelisted. Otherwise only the specified subattribute is kept but all other subattributes are removed. .RE .SH "SEE ALSO" \fBradsecproxy\fR(8) radsecproxy-1.11.1/tlv11.c0000644000076600000240000000616314722543325010746 /* Copyright (c) 2008-2009, UNINETT AS * Copyright (c) 2010, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "list.h" #include "tlv11.h" #include #include #include #include #include struct tlv *maketlv(uint8_t t, uint8_t l, void *v) { struct tlv *tlv; tlv = malloc(sizeof(struct tlv)); if (!tlv) return NULL; tlv->t = t; tlv->l = l; if (l && v) { tlv->v = malloc(l); if (!tlv->v) { free(tlv); return NULL; } memcpy(tlv->v, v, l); } else tlv->v = NULL; return tlv; } struct tlv *copytlv(struct tlv *in) { return in ? maketlv(in->t, in->l, in->v) : NULL; } void freetlv(struct tlv *tlv) { if (tlv) { if (tlv->v) { memset(tlv->v, 0, tlv->l); free(tlv->v); } free(tlv); } } int eqtlv(struct tlv *t1, struct tlv *t2) { if (!t1 || !t2) return t1 == t2; if (t1->t != t2->t || t1->l != t2->l) return 0; return memcmp(t1->v, t2->v, t1->l) == 0; } struct list *copytlvlist(struct list *tlvs) { struct list *out; struct list_node *node; if (!tlvs) return NULL; out = list_create(); if (!out) return NULL; for (node = list_first(tlvs); node; node = list_next(node)) { if (!list_push(out, copytlv((struct tlv *)node->data))) { freetlvlist(out); return NULL; } } return out; } void freetlvlist(struct list *tlvs) { struct tlv *tlv; while ((tlv = (struct tlv *)list_shift(tlvs))) freetlv(tlv); list_destroy(tlvs); } void rmtlv(struct list *tlvs, uint8_t t) { struct list_node *n, *p; struct tlv *tlv; p = NULL; n = list_first(tlvs); while (n) { tlv = (struct tlv *)n->data; if (tlv->t == t) { list_removedata(tlvs, tlv); freetlv(tlv); n = p ? list_next(p) : list_first(tlvs); } else { p = n; n = list_next(n); } } } uint8_t *tlv2str(struct tlv *tlv) { if (!tlv) return NULL; uint8_t *s = malloc(tlv->l + 1); if (s) { memcpy(s, tlv->v, tlv->l); s[tlv->l] = '\0'; } return s; } struct tlv *resizetlv(struct tlv *tlv, uint8_t newlen) { uint8_t *newv; if (newlen != tlv->l) { newv = realloc(tlv->v, newlen); if (newlen && !newv) return NULL; tlv->v = newv; tlv->l = newlen; } return tlv; } uint32_t tlv2longint(struct tlv *tlv) { if (!tlv) return 0; if (tlv->l != sizeof(uint32_t)) return 0; return ntohl(*(uint32_t *)tlv->v); } char *tlv2ipv4addr(struct tlv *tlv) { char *result; if (!tlv) return NULL; if (tlv->l != sizeof(in_addr_t)) return NULL; result = malloc(INET_ADDRSTRLEN); if (!result) return NULL; if (!inet_ntop(AF_INET, tlv->v, result, INET_ADDRSTRLEN)) { free(result); return NULL; } return result; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/hash.c0000644000076600000240000000660214722543325010720 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ #include "hash.h" #include "list.h" #include #include /* allocates and initialises hash structure; returns NULL if malloc fails */ struct hash *hash_create(void) { struct hash *h = malloc(sizeof(struct hash)); if (!h) return NULL; h->hashlist = list_create(); if (!h->hashlist) { free(h); return NULL; } pthread_mutex_init(&h->mutex, NULL); return h; } /* frees all memory associated with the hash */ void hash_destroy(struct hash *h) { struct list_node *ln; if (!h) return; for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) { free(((struct hash_entry *)ln->data)->key); free(((struct hash_entry *)ln->data)->data); } list_destroy(h->hashlist); pthread_mutex_destroy(&h->mutex); } /* insert entry in hash; returns 1 if ok, 0 if malloc fails */ int hash_insert(struct hash *h, void *key, uint32_t keylen, void *data) { struct hash_entry *e; if (!h) return 0; e = malloc(sizeof(struct hash_entry)); if (!e) return 0; memset(e, 0, sizeof(struct hash_entry)); e->key = malloc(keylen); if (!e->key) { free(e); return 0; } memcpy(e->key, key, keylen); e->keylen = keylen; e->data = data; pthread_mutex_lock(&h->mutex); if (!list_push(h->hashlist, e)) { pthread_mutex_unlock(&h->mutex); free(e->key); free(e); return 0; } pthread_mutex_unlock(&h->mutex); return 1; } /* reads entry from hash */ void *hash_read(struct hash *h, void *key, uint32_t keylen) { struct list_node *ln; struct hash_entry *e; if (!h) return 0; pthread_mutex_lock(&h->mutex); for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) { e = (struct hash_entry *)ln->data; if (e->keylen == keylen && !memcmp(e->key, key, keylen)) { pthread_mutex_unlock(&h->mutex); return e->data; } } pthread_mutex_unlock(&h->mutex); return NULL; } /* extracts entry from hash */ void *hash_extract(struct hash *h, void *key, uint32_t keylen) { struct list_node *ln; struct hash_entry *e; void *data; if (!h) return 0; pthread_mutex_lock(&h->mutex); for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) { e = (struct hash_entry *)ln->data; if (e->keylen == keylen && !memcmp(e->key, key, keylen)) { free(e->key); list_removedata(h->hashlist, e); data = e->data; free(e); pthread_mutex_unlock(&h->mutex); return data; } } pthread_mutex_unlock(&h->mutex); return NULL; } /* returns first entry */ struct hash_entry *hash_first(struct hash *hash) { struct list_node *ln; struct hash_entry *e; if (!hash || !((ln = list_first(hash->hashlist)))) return NULL; e = (struct hash_entry *)ln->data; e->next = ln->next; return e; } /* returns the next node after the argument */ struct hash_entry *hash_next(struct hash_entry *entry) { struct hash_entry *e; if (!entry || !entry->next) return NULL; e = (struct hash_entry *)entry->next->data; e->next = (struct list_node *)entry->next->next; return e; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/dtls.h0000644000076600000240000000030414722543325010741 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ const struct protodefs *dtlsinit(uint8_t h); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/gconfig.h0000644000076600000240000000205414722543325011413 /* Copyright (c) 2007-2008, UNINETT AS */ /* See LICENSE for licensing information. */ #define CONF_STR 1 #define CONF_CBK 2 #define CONF_MSTR 3 #define CONF_BLN 4 #define CONF_LINT 5 #define CONF_STR_NOESC 6 #define CONF_MSTR_NOESC 7 #include #include struct gconffile { char *path; FILE *file; const char *data; size_t datapos; }; int getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype); int getgenericconfig(struct gconffile **cf, char *block, ...); int pushgconfdata(struct gconffile **cf, const char *data); FILE *pushgconfpath(struct gconffile **cf, const char *path); FILE *pushgconffile(struct gconffile **cf, FILE *file, const char *description); FILE *pushgconfpaths(struct gconffile **cf, const char *path); int popgconf(struct gconffile **cf); void freegconfmstr(char **mstr); void freegconf(struct gconffile **cf); struct gconffile *openconfigfile(const char *file); int unhex(char *s, uint8_t process_null); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/README0000644000076600000240000000223614724610613010505 This is radsecproxy 1.11.1 radsecproxy is a generic RADIUS proxy that supports both UDP and TLS (RadSec) RADIUS transports. There is also experimental support for TCP and DTLS. The aim is for the proxy to have sufficient features to be flexible, while at the same time to be small, efficient and easy to configure. Official packages are available: Debian: apt-get install radsecproxy CentOS/RHEL/Rocky: yum install epel-release; yum install radsecproxy Fedora: dnf install radsecproxy FreeBSD: pkg install radsecproxy NetBSD: pkgin install radsecproxy Or built it from this source on most Unix like systems by simply typing ./configure && make For details see INSTALL To use radsecproxy you need to create a config file which is normally found in /etc/radsecproxy.conf or /usr/local/etc/radsecproxy.conf. You can also specify the location with the "-c" command line option (see below). For further instructions, please see the enclosed example file and the manpages radsecproxy(8) and radsecproxy.conf(5). Note for Cygwin users: Due to a bug in openssl the tls option CACertificatePath is currently unusable. Use a certificate bundle with CACertificateFile instead. radsecproxy-1.11.1/tlscommon.c0000644000076600000240000020306414722547152012013 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2010-2011,2015-2016, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) #define _GNU_SOURCE #include "debug.h" #include "hash.h" #include "hostport.h" #include "radsecproxy.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct hash *tlsconfs = NULL; #if OPENSSL_VERSION_NUMBER >= 0x10101000 static struct tls *tlsdefaultpsk = NULL; #endif #define COOKIE_SECRET_LENGTH 16 static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; static uint8_t cookie_secret_initialized = 0; int RSP_EX_DATA_CONFIG; int RSP_EX_DATA_CONFIG_LIST; struct certattrmatch { int (*matchfn)(GENERAL_NAME *, struct certattrmatch *); int type; char *exact; regex_t *regex; ASN1_OBJECT *oid; struct in6_addr ipaddr; int af; char *debugname; }; /* callbacks for making OpenSSL < 1.1 thread safe */ #if OPENSSL_VERSION_NUMBER < 0x10100000 static pthread_mutex_t *ssl_locks = NULL; #if OPENSSL_VERSION_NUMBER < 0x10000000 unsigned long ssl_thread_id() { return (unsigned long)pthread_self(); } #else void ssl_thread_id(CRYPTO_THREADID *id) { CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); } #endif void ssl_locking_callback(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) pthread_mutex_lock(&ssl_locks[type]); else pthread_mutex_unlock(&ssl_locks[type]); } #endif void sslinit(void) { #if OPENSSL_VERSION_NUMBER < 0x10100000 int i; SSL_library_init(); ssl_locks = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); if (!ssl_locks) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_init(&ssl_locks[i], NULL); } #if OPENSSL_VERSION_NUMBER < 0x10000000 CRYPTO_set_id_callback(ssl_thread_id); #else CRYPTO_THREADID_set_callback(ssl_thread_id); #endif CRYPTO_set_locking_callback(ssl_locking_callback); SSL_load_error_strings(); #else OPENSSL_init_ssl(0, NULL); RSP_EX_DATA_CONFIG = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0, NULL, NULL, NULL, NULL); RSP_EX_DATA_CONFIG_LIST = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0, NULL, NULL, NULL, NULL); #endif } /** * Print a human readable form of X509_NAME * * This is a direct replacement for X509_NAME_oneline() which should no longer be used. * * @param name The X509_Name to be printed. */ static char *print_x509_name(X509_NAME *name) { BIO *bio; char *buf; bio = BIO_new(BIO_s_mem()); if (!bio) { debug(DBG_ERR, "getcertsubject: BIO_new failed"); return NULL; } X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253); buf = malloc(BIO_number_written(bio) + 1); if (buf) { BIO_read(bio, buf, BIO_number_written(bio)); buf[BIO_number_written(bio)] = '\0'; } else { debug(DBG_ERR, "getcertsubject: malloc failed"); } BIO_free(bio); return buf; } static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) { int pwdlen = strlen(userdata); if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */ return 0; memcpy(buf, userdata, pwdlen); return pwdlen; } static int verify_cb(int ok, X509_STORE_CTX *ctx) { char *buf = NULL; X509 *err_cert; int err, depth; err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); if (depth > MAX_CERT_DEPTH) { ok = 0; err = X509_V_ERR_CERT_CHAIN_TOO_LONG; X509_STORE_CTX_set_error(ctx, err); } if (!ok) { if (err_cert) buf = print_x509_name(X509_get_subject_name(err_cert)); debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf ? buf : ""); free(buf); buf = NULL; switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: if (err_cert) { buf = print_x509_name(X509_get_issuer_name(err_cert)); if (buf) { debug(DBG_WARN, "\tIssuer=%s", buf); free(buf); buf = NULL; } } break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: debug(DBG_WARN, "\tCertificate not yet valid"); break; case X509_V_ERR_CERT_HAS_EXPIRED: debug(DBG_WARN, "Certificate has expired"); break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: debug(DBG_WARN, "Certificate no longer valid (after notAfter)"); break; case X509_V_ERR_NO_EXPLICIT_POLICY: debug(DBG_WARN, "No Explicit Certificate Policy"); break; } } #ifdef DEBUG printf("certificate verify returns %d", ok); #endif return ok; } static int cookie_calculate_hash(struct sockaddr *peer, time_t time, uint8_t *result, unsigned int *resultlength) { uint8_t *buf; int length; length = SOCKADDRP_SIZE(peer) + sizeof(time_t); buf = OPENSSL_malloc(length); if (!buf) { debug(DBG_ERR, "cookie_calculate_hash: malloc failed"); return 0; } memcpy(buf, &time, sizeof(time_t)); memcpy(buf + sizeof(time_t), peer, SOCKADDRP_SIZE(peer)); HMAC(EVP_sha256(), (const void *)cookie_secret, COOKIE_SECRET_LENGTH, buf, length, result, resultlength); OPENSSL_free(buf); return 1; } static int cookie_generate_cb(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) { struct sockaddr_storage peer; struct timeval now; uint8_t result[EVP_MAX_MD_SIZE] = {0}; unsigned int resultlength; if (!cookie_secret_initialized) { if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH)) debugx(1, DBG_ERR, "cookie_generate_cg: error generating random secret"); cookie_secret_initialized = 1; } if (BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer) <= 0) return 0; gettimeofday(&now, NULL); if (!cookie_calculate_hash((struct sockaddr *)&peer, now.tv_sec, result, &resultlength)) return 0; memcpy(cookie, &now.tv_sec, sizeof(time_t)); memcpy(cookie + sizeof(time_t), result, resultlength); *cookie_len = resultlength + sizeof(time_t); return 1; } #if OPENSSL_VERSION_NUMBER < 0x10100000 static int cookie_verify_cb(SSL *ssl, unsigned char *cookie, unsigned int cookie_len) { #else static int cookie_verify_cb(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len) { #endif struct sockaddr_storage peer; struct timeval now; time_t cookie_time; uint8_t result[EVP_MAX_MD_SIZE] = {0}; unsigned int resultlength; if (!cookie_secret_initialized) return 0; if (cookie_len < sizeof(time_t)) { debug(DBG_DBG, "cookie_verify_cb: cookie too short. ignoring."); return 0; } gettimeofday(&now, NULL); cookie_time = *(time_t *)cookie; if (now.tv_sec - cookie_time > 5) { debug(DBG_DBG, "cookie_verify_cb: cookie invalid or older than 5s. ignoring."); return 0; } if (BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer) <= 0) return 0; if (!cookie_calculate_hash((struct sockaddr *)&peer, cookie_time, result, &resultlength)) return 0; if (resultlength + sizeof(time_t) != cookie_len) { debug(DBG_DBG, "cookie_verify_cb: invalid cookie length. ignoring."); return 0; } if (memcmp(cookie + sizeof(time_t), result, resultlength)) { debug(DBG_DBG, "cookie_verify_cb: cookie not valid. ignoring."); return 0; } return 1; } #ifdef DEBUG static void ssl_info_callback(const SSL *ssl, int where, int ret) { const char *s; int w; w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT) s = "SSL_connect"; else if (w & SSL_ST_ACCEPT) s = "SSL_accept"; else s = "undefined"; if (where & SSL_CB_LOOP) debug(DBG_DBG, "%s:%s", s, SSL_state_string_long(ssl)); else if (where & SSL_CB_ALERT) { s = (where & SSL_CB_READ) ? "read" : "write"; debug(DBG_DBG, "SSL3 alert %s:%s:%s", s, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_EXIT) { if (ret == 0) debug(DBG_DBG, "%s:failed in %s", s, SSL_state_string_long(ssl)); else if (ret < 0) debug(DBG_DBG, "%s:error in %s", s, SSL_state_string_long(ssl)); } } #endif #if OPENSSL_VERSION_NUMBER >= 0x10101000 int psk_use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) { struct clsrvconf *conf = NULL; STACK_OF(SSL_CIPHER) * ciphers; const SSL_CIPHER *cipher; conf = (struct clsrvconf *)SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG); if (!conf || !conf->pskid || !conf->pskkey) { debug(DBG_DBG, "psk_use_session_cb: no PSK data configured for tls connection"); *sess = NULL; return 1; } debug(DBG_DBG, "psk_use_session_cb: using PSK id %s, key length %d", conf->pskid, conf->pskkeylen); *sess = SSL_SESSION_new(); if (!*sess) { debug(DBG_ERR, "psk_use_session_cb: failed to create new SSL session"); return 0; } *id = (unsigned char *)conf->pskid; *idlen = strlen(conf->pskid); if (!SSL_SESSION_set1_master_key(*sess, (unsigned char *)conf->pskkey, conf->pskkeylen)) { debug(DBG_ERR, "psk_use_session_cb: failed to set PSK key"); return 0; } if (!SSL_SESSION_set_protocol_version(*sess, TLS1_3_VERSION)) { debug(DBG_ERR, "psk_use_session_cb: failed to set tls version 1.3, mandatory for PSK!"); return 0; } ciphers = SSL_get1_supported_ciphers(ssl); if (!ciphers) { debug(DBG_ERR, "psk_use_session_cb: failed to get supported ciphers"); return 0; } cipher = sk_SSL_CIPHER_value(ciphers, 0); sk_SSL_CIPHER_free(ciphers); if (!cipher) { debug(DBG_ERR, "psk_use_session_cb: first supported cipher is null!"); return 0; } debug(DBG_DBG, "psk_use_session_cb: setting session cipher %s", SSL_CIPHER_get_name(cipher)); if (!SSL_SESSION_set_cipher(*sess, cipher)) { debug(DBG_ERR, "psk_use_session_cb: failed to set session cipher"); return 0; } /*disable certificate verification since we don't expect one for PSK*/ SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); return 1; } int psk_find_session_cb(SSL *ssl, const unsigned char *id, size_t idlen, SSL_SESSION **sess) { struct clsrvconf *conf = NULL; struct list *candidates = NULL; struct list_node *node = NULL; const SSL_CIPHER *cipher; if (!verifyutf8(id, idlen)) { debug(DBG_DBG, "psk_find_session_cb: id is not a valid utf-8 string, assuming session resumption"); *sess = NULL; return 1; } else if (idlen > PSK_ID_MAX_LENGTH) { debug(DBG_ERR, "psk_find_session_cb: id is longer than %d bytes", PSK_ID_MAX_LENGTH); *sess = NULL; return 0; } candidates = (struct list *)SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG_LIST); if (!candidates) debug(DBG_DBG, "psk_find_session_cb: no candidate list found in ssl object"); for (node = list_first(candidates); node; node = list_next(node)) { struct clsrvconf *candidate = (struct clsrvconf *)node->data; if (candidate->pskid && strcmp((const char *)id, candidate->pskid) == 0) { conf = candidate; break; } } if (!conf) { debug(DBG_ERR, "psk_find_session_cb: no client with PSK id %s found, rejecting connection", id); *sess = NULL; return 0; } debug(DBG_DBG, "psk_find_session_cb: PSK id %s matches client %s, key length %d", conf->pskid, conf->name, conf->pskkeylen); if (!SSL_set_ex_data(ssl, RSP_EX_DATA_CONFIG, conf)) { debug(DBG_ERR, "psk_find_session_cb: failed to set ssl ex data"); return 0; } *sess = SSL_SESSION_new(); if (!*sess) { debug(DBG_ERR, "psk_find_session_cb: failed to create new SSL session"); return 0; } if (!SSL_SESSION_set1_master_key(*sess, (unsigned char *)conf->pskkey, conf->pskkeylen)) { debug(DBG_ERR, "psk_find_session_cb: failed to set PSK key"); return 0; } if (!SSL_SESSION_set_protocol_version(*sess, TLS1_3_VERSION)) { debug(DBG_ERR, "psk_find_session_cb: failed to set tls version 1.3, mandatory for PSK!"); return 0; } cipher = SSL_get_pending_cipher(ssl); if (!cipher) { debug(DBG_ERR, "psk_find_session_cb: failed to get pending cipher"); return 0; } debug(DBG_DBG, "psk_find_session_cb: setting session cipher %s", SSL_CIPHER_get_name(cipher)); if (!SSL_SESSION_set_cipher(*sess, cipher)) { debug(DBG_ERR, "psk_find_session_cb: failed to set session cipher"); return 0; } SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); return 1; } void keylog_cb(const SSL *ssl, const char *line) { static FILE *keylog = NULL; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int keyloginitialized = 0; pthread_mutex_lock(&mutex); if (!keyloginitialized) { mode_t oldumask = umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (!(keylog = fopen(getenv(RSP_KEYLOG_ENV), "a"))) debugerrno(errno, DBG_ERR, "keylog_cb: error opening file %s", getenv(RSP_KEYLOG_ENV)); else setlinebuf(keylog); umask(oldumask); keyloginitialized = 1; } if (keylog) if (fputs(line, keylog) == EOF || fputc('\n', keylog) == EOF) { debugerrno(errno, DBG_ERR, "kehlog_cb: error writing to file %s", getenv(RSP_KEYLOG_ENV)); fclose(keylog); keylog = NULL; keyloginitialized = 0; } pthread_mutex_unlock(&mutex); } #endif static X509_VERIFY_PARAM *createverifyparams(char **poids) { X509_VERIFY_PARAM *pm; ASN1_OBJECT *pobject; int i; pm = X509_VERIFY_PARAM_new(); if (!pm) return NULL; for (i = 0; poids[i]; i++) { pobject = OBJ_txt2obj(poids[i], 0); if (!pobject) { X509_VERIFY_PARAM_free(pm); return NULL; } X509_VERIFY_PARAM_add0_policy(pm, pobject); } X509_VERIFY_PARAM_set_flags(pm, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY); return pm; } static int tlsaddcacrl(SSL_CTX *ctx, struct tls *conf) { STACK_OF(X509_NAME) * calist; X509_STORE *x509_s; unsigned long error; if (!conf->cacertfile && !conf->cacertpath) { debug(DBG_DBG, "tlsaddcacrl: No cacertifle or cacertpath specified for TLS %s, skip adding CAs", conf->name); return 1; } x509_s = X509_STORE_new(); if (!X509_STORE_load_locations(x509_s, conf->cacertfile, conf->cacertpath)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlsaddcacrl: Error loading CAs and CRLs in TLS context %s", conf->name); X509_STORE_free(x509_s); return 0; } if (conf->crlcheck) X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); if (conf->vpm) X509_STORE_set1_param(x509_s, conf->vpm); SSL_CTX_set_cert_store(ctx, x509_s); calist = sk_X509_NAME_new_null(); if (conf->cacertfile) { debug(DBG_DBG, "tlsaddcacrl: loading subject names from file %s", conf->cacertfile); if (!SSL_add_file_cert_subjects_to_stack(calist, conf->cacertfile)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlsaddcacrl: failed to load CA subject names from file %s", conf->cacertfile); } } if (conf->cacertpath) { debug(DBG_DBG, "tlsaddcacrl: loading subject names from path %s", conf->cacertpath); if (!SSL_add_dir_cert_subjects_to_stack(calist, conf->cacertpath)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlsaddcacrl: failed to load CA subject names from path %s", conf->cacertpath); } } ERR_clear_error(); /* add_dir_cert_subj returns errors on success */ SSL_CTX_set_client_CA_list(ctx, calist); debug(DBG_DBG, "tlsaddcacrl: updated TLS context %s", conf->name); return 1; } static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) { SSL_CTX *ctx = NULL; unsigned long error; switch (type) { #ifdef RADPROT_TLS case RAD_TLS: #if OPENSSL_VERSION_NUMBER >= 0x10100000 /* TLS_method() was introduced in OpenSSL 1.1.0. */ ctx = SSL_CTX_new(TLS_method()); if (ctx != NULL) { if (conf->tlsminversion >= 0) SSL_CTX_set_min_proto_version(ctx, conf->tlsminversion); if (conf->tlsmaxversion >= 0) SSL_CTX_set_max_proto_version(ctx, conf->tlsmaxversion); } #else /* No TLS_method(), use SSLv23_method() and disable SSLv2 and SSLv3. */ ctx = SSL_CTX_new(SSLv23_method()); if (ctx != NULL) { SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); } #endif #ifdef DEBUG if (ctx != NULL) { SSL_CTX_set_info_callback(ctx, ssl_info_callback); } #endif break; #endif #ifdef RADPROT_DTLS case RAD_DTLS: #if OPENSSL_VERSION_NUMBER >= 0x10002000 /* DTLS_method() seems to have been introduced in OpenSSL 1.0.2. */ ctx = SSL_CTX_new(DTLS_method()); #if OPENSSL_VERSION_NUMBER >= 0x10100000 if (ctx != NULL) { if (conf->dtlsminversion >= 0) SSL_CTX_set_min_proto_version(ctx, conf->dtlsminversion); if (conf->dtlsmaxversion >= 0) SSL_CTX_set_max_proto_version(ctx, conf->dtlsmaxversion); } #endif #else ctx = SSL_CTX_new(DTLSv1_method()); #endif #ifdef DEBUG if (ctx != NULL) { SSL_CTX_set_info_callback(ctx, ssl_info_callback); } #endif if (ctx != NULL) { SSL_CTX_set_read_ahead(ctx, 1); } break; #endif } if (!ctx) { debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name); return NULL; } #if OPENSSL_VERSION_NUMBER < 0x10100000L { long sslversion = SSLeay(); if (sslversion < 0x00908100L || (sslversion >= 0x10000000L && sslversion < 0x10000020L)) { debug(DBG_WARN, "%s: %s seems to be of a version with a " "certain security critical bug (fixed in OpenSSL 0.9.8p and " "1.0.0b). Disabling OpenSSL session caching for context %p.", __func__, SSLeay_version(SSLEAY_VERSION), ctx); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); } } #endif if (conf->certkeypwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); } if (conf->certfile) { if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlscreatectx: Error reading certificate in TLS context %s", conf->name); ERR_clear_error(); SSL_CTX_free(ctx); return NULL; } if (!SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlscreatectx: Error reading privatekey in TLS context %s", conf->name); ERR_clear_error(); SSL_CTX_free(ctx); return NULL; } } else { debug(DBG_DBG, "tlsloadclientcert: no certificate specified, TLS %s can only be used for TLS-PSK", conf->name); } if (conf->policyoids) { if (!conf->vpm) { conf->vpm = createverifyparams(conf->policyoids); if (!conf->vpm) { debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } } if (!tlsaddcacrl(ctx, conf)) { if (conf->vpm) { X509_VERIFY_PARAM_free(conf->vpm); conf->vpm = NULL; } SSL_CTX_free(ctx); return NULL; } if (conf->cipherlist) { if (!SSL_CTX_set_cipher_list(ctx, conf->cipherlist)) { debug(DBG_ERR, "tlscreatectx: Failed to set cipher list in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); #if OPENSSL_VERSION_NUMBER >= 0x10101000 /* TLS 1.3 stuff */ if (conf->ciphersuites) { if (!SSL_CTX_set_ciphersuites(ctx, conf->ciphersuites)) { debug(DBG_ERR, "tlscreatectx: Failed to set ciphersuites in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } if (!SSL_CTX_set_num_tickets(ctx, 0)) debug(DBG_ERR, "tlscreatectx: Failed to set num tickets in TLS context %s", conf->name); #endif if (conf->dhparam) { #if OPENSSL_VERSION_NUMBER >= 0x30000000 if (!SSL_CTX_set0_tmp_dh_pkey(ctx, conf->dhparam)) { #else if (!SSL_CTX_set_tmp_dh(ctx, conf->dhparam)) { #endif while ((error = ERR_get_error())) debug(DBG_WARN, "tlscreatectx: SSL: %s", ERR_error_string(error, NULL)); debug(DBG_WARN, "tlscreatectx: Failed to set dh params. Can continue, but some ciphers might not be available."); } } #if OPENSSL_VERSION_NUMBER >= 0x10101000 else { if (!SSL_CTX_set_dh_auto(ctx, 1)) { while ((error = ERR_get_error())) debug(DBG_WARN, "tlscreatectx: SSL: %s", ERR_error_string(error, NULL)); debug(DBG_WARN, "tlscreatectx: Failed to set automatic dh params. Can continue, but some ciphers might not be available."); } } #endif SSL_CTX_set_cookie_generate_cb(ctx, cookie_generate_cb); SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify_cb); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb); SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1); #if OPENSSL_VERSION_NUMBER >= 0x10101000 SSL_CTX_set_psk_use_session_callback(ctx, psk_use_session_cb); SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb); SSL_CTX_set_options(ctx, SSL_CTX_get_options(ctx) & ~SSL_OP_ALLOW_NO_DHE_KEX); if (getenv(RSP_KEYLOG_ENV)) SSL_CTX_set_keylog_callback(ctx, keylog_cb); #endif debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name); return ctx; } struct tls *tlsgettls(char *conf) { return hash_read(tlsconfs, conf, strlen(conf)); } struct tls *tlsgetdefaultpsk(void) { #if OPENSSL_VERSION_NUMBER >= 0x10101000 if (!tlsdefaultpsk) { if (!(tlsdefaultpsk = calloc(1, sizeof(struct tls)))) { debug(DBG_ERR, "malloc failed"); return NULL; } tlsdefaultpsk->name = "_psk_default"; tlsdefaultpsk->ciphersuites = "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; tlsdefaultpsk->tlsminversion = TLS1_3_VERSION; } return tlsdefaultpsk; #else debugx(1, DBG_ERR, "tlsgetdefaultpsk: use of TLS1.3-PSK requires openssl >= 1.1.1"); return NULL; #endif } SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) { struct timeval now; if (!t) return NULL; gettimeofday(&now, NULL); switch (type) { #ifdef RADPROT_TLS case RAD_TLS: if (t->tlsexpiry && t->tlsctx) { if (t->tlsexpiry <= now.tv_sec) { t->tlsexpiry = now.tv_sec + t->cacheexpiry; if (!tlsaddcacrl(t->tlsctx, t)) debug(DBG_WARN, "tlsgetctx: cache reload for TLS context %s failed, continue with old state!", t->name); } } if (!t->tlsctx) { t->tlsctx = tlscreatectx(RAD_TLS, t); if (t->cacheexpiry >= 0) t->tlsexpiry = now.tv_sec + t->cacheexpiry; } return t->tlsctx; #endif #ifdef RADPROT_DTLS case RAD_DTLS: if (t->dtlsexpiry && t->dtlsctx) { if (t->dtlsexpiry <= now.tv_sec) { t->dtlsexpiry = now.tv_sec + t->cacheexpiry; if (!tlsaddcacrl(t->dtlsctx, t)) debug(DBG_WARN, "tlsgetctx: cache reload for DTLS context %s failed, continue with old state!", t->name); } } if (!t->dtlsctx) { t->dtlsctx = tlscreatectx(RAD_DTLS, t); if (t->cacheexpiry >= 0) t->dtlsexpiry = now.tv_sec + t->cacheexpiry; } return t->dtlsctx; #endif } return NULL; } void tlsreload(void) { struct tls *conf; struct hash_entry *entry; struct timeval now; SSL_CTX *newctx; debug(DBG_NOTICE, "reloading certs, CAs, CRLs"); gettimeofday(&now, NULL); for (entry = hash_first(tlsconfs); entry; entry = hash_next(entry)) { conf = (struct tls *)entry->data; #ifdef RADPROT_TLS pthread_mutex_lock(&conf->lock); if (conf->tlsctx) { if (conf->tlsexpiry) conf->tlsexpiry = now.tv_sec + conf->cacheexpiry; newctx = tlscreatectx(RAD_TLS, conf); if (!newctx) { debug(DBG_ERR, "tlsreload: failed to create new TLS context for %s, context is NOT updated!", conf->name); } else { SSL_CTX_free(conf->tlsctx); conf->tlsctx = newctx; } } pthread_mutex_unlock(&conf->lock); #endif #ifdef RADPROT_DTLS pthread_mutex_lock(&conf->lock); if (conf->dtlsctx) { if (conf->dtlsexpiry) conf->dtlsexpiry = now.tv_sec + conf->cacheexpiry; newctx = tlscreatectx(RAD_DTLS, conf); if (!newctx) { debug(DBG_ERR, "tlsreload: failed to create new DTLS context for %s, context is NOT updated!", conf->name); } else { SSL_CTX_free(conf->dtlsctx); conf->dtlsctx = newctx; } } pthread_mutex_unlock(&conf->lock); #endif } } X509 *verifytlscert(SSL *ssl) { X509 *cert; unsigned long error; if (SSL_get_verify_result(ssl) != X509_V_OK) { debug(DBG_ERR, "verifytlscert: basic validation failed"); while ((error = ERR_get_error())) debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL)); return NULL; } cert = SSL_get_peer_certificate(ssl); if (!cert) debug(DBG_ERR, "verifytlscert: failed to obtain certificate"); return cert; } static int certattr_matchrid(GENERAL_NAME *gn, struct certattrmatch *match) { return OBJ_cmp(gn->d.registeredID, match->oid) == 0 ? 1 : 0; } static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match) { int l = ASN1_STRING_length(gn->d.iPAddress); return (((match->af == AF_INET && l == sizeof(struct in_addr)) || (match->af == AF_INET6 && l == sizeof(struct in6_addr))) && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0; } static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { char *s; if (l <= 0) return 0; if (match->exact) { if (l == strlen(match->exact) && memcmp(v, match->exact, l) == 0) return 1; return 0; } s = stringcopy((char *)v, l); if (!s) { debug(DBG_ERR, "malloc failed"); return 0; } debug(DBG_DBG, "matchtregex: matching %s", s); if (regexec(match->regex, s, 0, NULL, 0) == 0) { free(s); return 1; } free(s); return 0; } static int certattr_matchregex(GENERAL_NAME *gn, struct certattrmatch *match) { return _general_name_regex_match((char *)ASN1_STRING_get0_data(gn->d.ia5), ASN1_STRING_length(gn->d.ia5), match); } static int certattr_matchothername(GENERAL_NAME *gn, struct certattrmatch *match) { if (OBJ_cmp(gn->d.otherName->type_id, match->oid) != 0) return 0; return _general_name_regex_match((char *)ASN1_STRING_get0_data(gn->d.otherName->value->value.octet_string), ASN1_STRING_length(gn->d.otherName->value->value.octet_string), match); } static int certattr_matchcn(X509 *cert, struct certattrmatch *match) { int loc; X509_NAME *nm; X509_NAME_ENTRY *e; ASN1_STRING *t; nm = X509_get_subject_name(cert); loc = -1; for (;;) { loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc); if (loc == -1) break; e = X509_NAME_get_entry(nm, loc); t = X509_NAME_ENTRY_get_data(e); if (_general_name_regex_match((char *)ASN1_STRING_get0_data(t), ASN1_STRING_length(t), match)) return 1; } return 0; } /* returns 1 if expected type is present and matches 0 if expected type is not present -1 if expected type is present but does not match */ static int matchsubjaltname(X509 *cert, struct certattrmatch *match) { GENERAL_NAME *gn; int loc, n, i, r = 0; char *fail = NULL, *tmp, *s; STACK_OF(GENERAL_NAME) * alt; /*special case: don't search in SAN, but CN field in subject */ if (match->type == -1) return certattr_matchcn(cert, match); loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); if (loc < 0) return 0; alt = X509V3_EXT_d2i(X509_get_ext(cert, loc)); if (!alt) return 0; n = sk_GENERAL_NAME_num(alt); for (i = 0; i < n; i++) { gn = sk_GENERAL_NAME_value(alt, i); if (gn->type == match->type) { r = match->matchfn(gn, match); if (r) break; r = -1; } /*legacy print non-matching SAN*/ if (gn->type == GEN_DNS || gn->type == GEN_URI) { s = stringcopy((char *)ASN1_STRING_get0_data(gn->d.ia5), ASN1_STRING_length(gn->d.ia5)); if (!s) continue; tmp = fail; if (asprintf(&fail, "%s%s%s", tmp ? tmp : "", tmp ? ", " : "", s) >= 0) free(tmp); else fail = tmp; free(s); } } if (r < 1) debug(DBG_DBG, "matchsubjaltname: no matching Subject Alt Name found! (%s)", fail ? fail : "no dNSName or URI entry"); free(fail); GENERAL_NAMES_free(alt); return r; } int certnamecheck(X509 *cert, struct hostportres *hp) { int r = 0; struct certattrmatch match; memset(&match, 0, sizeof(struct certattrmatch)); r = 0; if (hp->prefixlen != 255) { /* we disable the check for prefixes */ return 1; } if (inet_pton(AF_INET, hp->host, &match.ipaddr)) match.af = AF_INET; else if (inet_pton(AF_INET6, hp->host, &match.ipaddr)) match.af = AF_INET6; else match.af = 0; match.exact = hp->host; if (match.af) { match.matchfn = &certattr_matchip; match.type = GEN_IPADD; r = matchsubjaltname(cert, &match); } if (!r) { match.matchfn = &certattr_matchregex; match.type = GEN_DNS; r = matchsubjaltname(cert, &match); } if (r) { if (r > 0) { debug(DBG_DBG, "certnamecheck: Found subjectaltname matching %s %s", match.af ? "address" : "host", hp->host); return 1; } debug(DBG_WARN, "certnamecheck: No subjectaltname matching %s %s", match.af ? "address" : "host", hp->host); } else { /* as per RFC 6125 6.4.4: CN MUST NOT be matched if SAN is present */ if (certattr_matchcn(cert, &match)) { debug(DBG_DBG, "certnamecheck: Found cn matching host %s", hp->host); return 1; } debug(DBG_WARN, "certnamecheck: cn not matching host %s", hp->host); } return 0; } int certnamecheckany(X509 *cert, struct list *hostports) { struct list_node *entry; for (entry = list_first(hostports); entry; entry = list_next(entry)) { if (certnamecheck(cert, (struct hostportres *)entry->data)) return 1; } return 0; } int verifyconfcert(X509 *cert, struct clsrvconf *conf, struct hostportres *hpconnected) { char *subject; int ok = 1; struct list_node *entry; subject = getcertsubject(cert); debug(DBG_DBG, "verifyconfcert: verify certificate for host %s, subject %s", conf->name, subject); if (conf->certnamecheck) { debug(DBG_DBG, "verifyconfcert: verify hostname"); if (conf->servername) { struct hostportres servername = {.host = conf->servername, .port = NULL, .prefixlen = 255, .addrinfo = NULL}; if (!certnamecheck(cert, &servername)) { debug(DBG_WARN, "verifyconfcert: certificate name check failed for host %s (%s)", conf->name, servername.host); ok = 0; } } else if (hpconnected) { if (!certnamecheck(cert, hpconnected)) { debug(DBG_WARN, "verifyconfcert: certificate name check failed for host %s (%s)", conf->name, hpconnected->host); ok = 0; } } else { if (!certnamecheckany(cert, conf->hostports)) { debug(DBG_DBG, "verifyconfcert: no matching CN or SAN found for host %s", conf->name); ok = 0; } } } for (entry = list_first(conf->matchcertattrs); entry; entry = list_next(entry)) { if (matchsubjaltname(cert, (struct certattrmatch *)entry->data) < 1) { debug(DBG_WARN, "verifyconfcert: %s not matching for host %s (%s)", ((struct certattrmatch *)entry->data)->debugname, conf->name, subject); ok = 0; } else { debug(DBG_DBG, "verifyconfcert: %s matching for host %s (%s)", ((struct certattrmatch *)entry->data)->debugname, conf->name, subject); } } free(subject); return ok; } char *getcertsubject(X509 *cert) { if (!cert) return NULL; return print_x509_name(X509_get_subject_name(cert)); } #if OPENSSL_VERSION_NUMBER >= 0x10100000 static int parse_tls_version(uint8_t dtls, const char *version) { if (!strcasecmp("", version)) return 0; if (dtls) { if (!strcasecmp("DTLS1", version)) return DTLS1_VERSION; if (!strcasecmp("DTLS1_2", version)) return DTLS1_2_VERSION; } else { if (!strcasecmp("SSL3", version)) return SSL3_VERSION; if (!strcasecmp("TLS1", version)) return TLS1_VERSION; if (!strcasecmp("TLS1_1", version)) return TLS1_1_VERSION; if (!strcasecmp("TLS1_2", version)) return TLS1_2_VERSION; #if OPENSSL_VERSION_NUMBER >= 0x10101000 if (!strcasecmp("TLS1_3", version)) return TLS1_3_VERSION; #endif } return -1; } static int conf_tls_version(uint8_t dtls, const char *version, int *min, int *max) { char *ver, *s, *smin, *smax; ver = stringcopy(version, strlen(version)); s = strchr(ver, ':'); if (!s) { smin = smax = ver; } else { *s = '\0'; smin = ver; smax = s + 1; } *min = parse_tls_version(dtls, smin); *max = parse_tls_version(dtls, smax); free(ver); return *min >= 0 && *max >= 0 && (*max == 0 || *min <= *max); } #endif int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct tls *conf; char *tlsversion = NULL; char *dtlsversion = NULL; char *dhfile = NULL; unsigned long error; debug(DBG_DBG, "conftls_cb called for %s", block); conf = calloc(1, sizeof(struct tls)); if (!conf) { debug(DBG_ERR, "conftls_cb: malloc failed"); return 0; } conf->cacheexpiry = -1; if (!getgenericconfig(cf, block, "CACertificateFile", CONF_STR, &conf->cacertfile, "CACertificatePath", CONF_STR, &conf->cacertpath, "CertificateFile", CONF_STR, &conf->certfile, "CertificateKeyFile", CONF_STR, &conf->certkeyfile, "CertificateKeyPassword", CONF_STR, &conf->certkeypwd, "CacheExpiry", CONF_LINT, &conf->cacheexpiry, "CRLCheck", CONF_BLN, &conf->crlcheck, "PolicyOID", CONF_MSTR, &conf->policyoids, "CipherList", CONF_STR, &conf->cipherlist, "CipherSuites", CONF_STR, &conf->ciphersuites, "TlsVersion", CONF_STR, &tlsversion, "DtlsVersion", CONF_STR, &dtlsversion, "DhFile", CONF_STR, &dhfile, NULL)) { debug(DBG_ERR, "conftls_cb: configuration error in block %s", val); goto errexit; } if (!conf->certfile) { debug(DBG_DBG, "conftls_db: tls %s has no certificate specified, can only be used for PSK", val); } else { if (!conf->certkeyfile) { debug(DBG_ERR, "conftls_cb: TLSCertificateKeyFile must be specified together with TLSCertificateFile in block %s", val); goto errexit; } if (!conf->cacertfile && !conf->cacertpath) { debug(DBG_ERR, "conftls_cb: CA Certificate file or path need to be specified together with TLSCertificateFile in block %s", val); goto errexit; } } #if OPENSSL_VERSION_NUMBER >= 0x10100000 /* use -1 as 'not set' value */ conf->tlsminversion = conf->tlsmaxversion = conf->dtlsminversion = conf->dtlsmaxversion = -1; if (tlsversion) { if (!conf_tls_version(0, tlsversion, &conf->tlsminversion, &conf->tlsmaxversion)) { debug(DBG_ERR, "error in block %s, invalid TlsVersion %s", val, tlsversion); goto errexit; } free(tlsversion); tlsversion = NULL; } if (dtlsversion) { if (!conf_tls_version(1, dtlsversion, &conf->dtlsminversion, &conf->dtlsmaxversion)) { debug(DBG_ERR, "error in block %s, invalid DtlsVersion %s", val, dtlsversion); goto errexit; } free(dtlsversion); dtlsversion = NULL; } #else if (tlsversion || dtlsversion) { debug(DBG_ERR, "error in block %s, setting tls/dtls version requires openssl 1.1.0 or later", val); goto errexit; } #endif if (dhfile) { #if OPENSSL_VERSION_NUMBER >= 0x30000000 BIO *bio = BIO_new_file(dhfile, "r"); if (bio) { conf->dhparam = EVP_PKEY_new(); if (!PEM_read_bio_Parameters(bio, &conf->dhparam)) { BIO_free(bio); while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "error in block %s: Failed to load DhFile %s.", val, dhfile); goto errexit; } BIO_free(bio); } #else FILE *dhfp = fopen(dhfile, "r"); if (dhfp) { conf->dhparam = PEM_read_DHparams(dhfp, NULL, NULL, NULL); fclose(dhfp); if (!conf->dhparam) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "error in block %s: Failed to load DhFile %s.", val, dhfile); goto errexit; } } else { debug(DBG_ERR, "error in block %s, DhFile: can't open file %s", val, dhfile); goto errexit; } free(dhfile); dhfile = NULL; #endif } conf->name = stringcopy(val, 0); if (!conf->name) { debug(DBG_ERR, "conftls_cb: malloc failed"); goto errexit; } pthread_mutex_init(&conf->lock, NULL); if (!tlsconfs) tlsconfs = hash_create(); if (!hash_insert(tlsconfs, val, strlen(val), conf)) { debug(DBG_ERR, "conftls_cb: malloc failed"); goto errexit; } if (!tlsgetctx(RAD_TLS, conf)) { debug(DBG_ERR, "conftls_cb: error creating ctx for TLS block %s", val); goto errexit; } debug(DBG_DBG, "conftls_cb: added TLS block %s", val); return 1; errexit: free(conf->cacertfile); free(conf->cacertpath); free(conf->certfile); free(conf->certkeyfile); free(conf->certkeypwd); freegconfmstr(conf->policyoids); free(tlsversion); free(dtlsversion); free(dhfile); #if OPENSSL_VERSION_NUMBER >= 0x30000000 EVP_PKEY_free(conf->dhparam); #else DH_free(conf->dhparam); #endif free(conf); return 0; } static regex_t *compileregex(char *regstr) { regex_t *result; if (regstr[0] != '/') return NULL; regstr++; if (regstr[strlen(regstr) - 1] == '/') regstr[strlen(regstr) - 1] = '\0'; if (!*regstr) return NULL; result = malloc(sizeof(regex_t)); if (!result) { debug(DBG_ERR, "malloc failed"); return NULL; } if (regcomp(result, regstr, REG_EXTENDED | REG_ICASE | REG_NOSUB)) { free(result); debug(DBG_ERR, "failed to compile regular expression %s", regstr); return NULL; } return result; } int addmatchcertattr(struct clsrvconf *conf, const char *match) { struct certattrmatch *certattrmatch; char *pos, *colon, *matchcopy; if (!conf->matchcertattrs) { conf->matchcertattrs = list_create(); } certattrmatch = malloc(sizeof(struct certattrmatch)); if (!certattrmatch) return 0; memset(certattrmatch, 0, sizeof(struct certattrmatch)); matchcopy = stringcopy(match, 0); pos = matchcopy; colon = strchr(pos, ':'); if (!colon) goto errexit; if (strncasecmp(pos, "CN", colon - pos) == 0) { if (!(certattrmatch->regex = compileregex(colon + 1))) goto errexit; certattrmatch->type = -1; certattrmatch->matchfn = NULL; /*special case: don't search in SAN, but CN field in subject */ } else if (strncasecmp(pos, "SubjectAltName", colon - pos) == 0) { pos = colon + 1; colon = strchr(pos, ':'); if (!colon) goto errexit; if (strncasecmp(pos, "IP", colon - pos) == 0) { pos = colon + 1; if (inet_pton(AF_INET, pos, &certattrmatch->ipaddr)) certattrmatch->af = AF_INET; else if (inet_pton(AF_INET6, pos, &certattrmatch->ipaddr)) certattrmatch->af = AF_INET6; else goto errexit; certattrmatch->type = GEN_IPADD; certattrmatch->matchfn = &certattr_matchip; } else if (strncasecmp(pos, "URI", colon - pos) == 0) { if (!(certattrmatch->regex = compileregex(colon + 1))) goto errexit; certattrmatch->type = GEN_URI; certattrmatch->matchfn = &certattr_matchregex; } else if (strncasecmp(pos, "DNS", colon - pos) == 0) { if (!(certattrmatch->regex = compileregex(colon + 1))) goto errexit; certattrmatch->type = GEN_DNS; certattrmatch->matchfn = &certattr_matchregex; } else if (strncasecmp(pos, "rID", colon - pos) == 0) { certattrmatch->oid = OBJ_txt2obj(colon + 1, 0); if (!certattrmatch->oid) goto errexit; certattrmatch->type = GEN_RID; certattrmatch->matchfn = &certattr_matchrid; } else if (strncasecmp(pos, "otherNAme", colon - pos) == 0) { pos = colon + 1; colon = strchr(pos, ':'); if (!colon) goto errexit; *colon = '\0'; if (!(certattrmatch->oid = OBJ_txt2obj(pos, 0))) goto errexit; if (!(certattrmatch->regex = compileregex(colon + 1))) goto errexit; certattrmatch->type = GEN_OTHERNAME; certattrmatch->matchfn = &certattr_matchothername; } else goto errexit; } else goto errexit; certattrmatch->debugname = stringcopy(match, 0); if (!list_push(conf->matchcertattrs, certattrmatch)) goto errexit; free(matchcopy); return 1; errexit: free(certattrmatch); free(matchcopy); return 0; } void freematchcertattr(struct clsrvconf *conf) { struct list_node *entry; struct certattrmatch *match; if (conf->matchcertattrs) { for (entry = list_first(conf->matchcertattrs); entry; entry = list_next(entry)) { match = ((struct certattrmatch *)entry->data); free(match->debugname); free(match->exact); ASN1_OBJECT_free(match->oid); if (match->regex) regfree(match->regex); free(match->regex); } list_destroy(conf->matchcertattrs); conf->matchcertattrs = NULL; } } int tlssetsni(SSL *ssl, char *sni) { return SSL_set_tlsext_host_name(ssl, sni); } int sslaccepttimeout(SSL *ssl, int timeout) { int socket, origflags, ndesc, r = -1, sockerr = 0; socklen_t errlen = sizeof(sockerr); struct pollfd fds[1]; uint8_t want_write = 1; socket = SSL_get_fd(ssl); origflags = fcntl(socket, F_GETFL, 0); if (origflags == -1) { debugerrno(errno, DBG_WARN, "Failed to get flags"); return -1; } if (fcntl(socket, F_SETFL, origflags | O_NONBLOCK) == -1) { debugerrno(errno, DBG_WARN, "Failed to set O_NONBLOCK"); return -1; } while (r < 1) { fds[0].fd = socket; fds[0].events = POLLIN; if (want_write) { fds[0].events |= POLLOUT; want_write = 0; } if ((ndesc = poll(fds, 1, timeout * 1000)) < 1) { if (ndesc == 0) debug(DBG_DBG, "sslaccepttimeout: timeout during SSL_accept"); else debugerrno(errno, DBG_DBG, "sslaccepttimeout: poll error"); break; } if (fds[0].revents & POLLERR) { if (!getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &errlen)) debug(DBG_WARN, "SSL Accept failed: %s", strerror(sockerr)); else debug(DBG_WARN, "SSL Accept failed: unknown error"); } else if (fds[0].revents & POLLHUP) { debug(DBG_WARN, "SSL Accept error: hang up"); } else if (fds[0].revents & POLLNVAL) { debug(DBG_WARN, "SSL Accept error: fd not open"); } else { r = SSL_accept(ssl); if (r <= 0) { switch (SSL_get_error(ssl, r)) { case SSL_ERROR_WANT_WRITE: want_write = 1; case SSL_ERROR_WANT_READ: continue; case SSL_ERROR_SYSCALL: debugerrno(errno, DBG_ERR, "sslaccepttimeout: syscall error "); } } } break; } if (fcntl(socket, F_SETFL, origflags) == -1) debugerrno(errno, DBG_WARN, "Failed to set original flags back"); return r; } int sslconnecttimeout(SSL *ssl, int timeout) { int socket, origflags, ndesc, r = -1, sockerr = 0; socklen_t errlen = sizeof(sockerr); struct pollfd fds[1]; uint8_t want_write = 1; socket = SSL_get_fd(ssl); origflags = fcntl(socket, F_GETFL, 0); if (origflags == -1) { debugerrno(errno, DBG_WARN, "Failed to get flags"); return -1; } if (fcntl(socket, F_SETFL, origflags | O_NONBLOCK) == -1) { debugerrno(errno, DBG_WARN, "Failed to set O_NONBLOCK"); return -1; } while (r < 1) { fds[0].fd = socket; fds[0].events = POLLIN; if (want_write) { fds[0].events |= POLLOUT; want_write = 0; } if ((ndesc = poll(fds, 1, timeout * 1000)) < 1) { if (ndesc == 0) debug(DBG_DBG, "sslconnecttimeout: timeout during SSL_connect"); else debugerrno(errno, DBG_DBG, "sslconnecttimeout: poll error"); break; } if (fds[0].revents & POLLERR) { if (!getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &errlen)) debug(DBG_WARN, "SSL Connection failed: %s", strerror(sockerr)); else debug(DBG_WARN, "SSL Connection failed: unknown error"); } else if (fds[0].revents & POLLHUP) { debug(DBG_WARN, "SSL Connect error: hang up"); } else if (fds[0].revents & POLLNVAL) { debug(DBG_WARN, "SSL Connect error: fd not open"); } else { r = SSL_connect(ssl); if (r <= 0) { switch (SSL_get_error(ssl, r)) { case SSL_ERROR_WANT_WRITE: want_write = 1; case SSL_ERROR_WANT_READ: continue; } } } break; } if (fcntl(socket, F_SETFL, origflags) == -1) debugerrno(errno, DBG_WARN, "Failed to set original flags back"); return r; } /** * @brief read from ssl connection with timeout. * In case of error, ssl connection will be closed and shutdown state is set. * * @param ssl SSL connection * @param buf destination buffer * @param num number of bytes to read * @param timeout maximum time to wait for data, 0 waits indefinetely * @param lock the lock to aquire before performing any operation on the ssl connection * @return number of bytes received, 0 on timeout, -1 on error (connection lost) */ int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_mutex_t *lock) { int ndesc, cnt = 0, len, sockerr = 0; socklen_t errlen = sizeof(sockerr); struct pollfd fds[1]; unsigned long error; uint8_t want_write = 0; assert(lock); pthread_mutex_lock(lock); for (len = 0; len < num; len += cnt) { if (SSL_pending(ssl) == 0) { fds[0].fd = SSL_get_fd(ssl); fds[0].events = POLLIN; if (want_write) { fds[0].events |= POLLOUT; want_write = 0; } pthread_mutex_unlock(lock); ndesc = poll(fds, 1, timeout ? timeout * 1000 : -1); if (ndesc == 0) return ndesc; pthread_mutex_lock(lock); if (ndesc < 0 || fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { if (fds[0].revents & POLLERR) { if (!getsockopt(SSL_get_fd(ssl), SOL_SOCKET, SO_ERROR, (void *)&sockerr, &errlen)) debug(DBG_INFO, "sslreadtimeout: connection lost: %s", strerror(sockerr)); else debug(DBG_INFO, "sslreadtimeout: connection lost: unknown error"); } else if (fds[0].revents & POLLHUP) { debug(DBG_INFO, "sslreadtimeout: connection lost: hang up"); } else if (fds[0].revents & POLLNVAL) { debug(DBG_ERR, "sslreadtimeout: connection error: fd not open"); } SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); pthread_mutex_unlock(lock); return -1; } } cnt = SSL_read(ssl, buf + len, num - len); if (cnt <= 0) { switch (SSL_get_error(ssl, cnt)) { case SSL_ERROR_WANT_WRITE: want_write = 1; /* fallthrough */ case SSL_ERROR_WANT_READ: cnt = 0; continue; case SSL_ERROR_ZERO_RETURN: debug(DBG_DBG, "sslreadtimeout: got ssl shutdown"); SSL_shutdown(ssl); break; case SSL_ERROR_SYSCALL: if (errno) debugerrno(errno, DBG_INFO, "sslreadtimeout: connection lost"); else debug(DBG_INFO, "sslreadtimeout: connection lost: EOF"); /* fallthrough */ case SSL_ERROR_SSL: while ((error = ERR_get_error())) debug(DBG_ERR, "sslreadtimeout: SSL: %s", ERR_error_string(error, NULL)); SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); break; default: debug(DBG_ERR, "sslreadtimeout: uncaught SSL error"); SSL_shutdown(ssl); SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); } pthread_mutex_unlock(lock); return -1; } } pthread_mutex_unlock(lock); return cnt; } /** * @brief write to a ssl session. * * When called as blocking, it will only return once the data has been fully written, * an error has occured or the SSL session has been shut down. * * @param ssl SSL session to write to * @param buf buffer to write * @param num number of bytes from buffer to write * @param blocking block until num bytes have been written or error occurs * @return int number of bytes written or 0 if it would block, or -1 on error */ int sslwrite(SSL *ssl, void *buf, int num, uint8_t blocking) { int ret = -1; unsigned long error; struct pollfd fds[1]; uint8_t want_read = 0; if (!buf || num <= 0) { debug(DBG_ERR, "dosslwrite: was called with empty or invalid buffer!"); return -1; } while (!SSL_get_shutdown(ssl)) { fds[0].fd = SSL_get_fd(ssl); fds[0].events = POLLOUT; if (want_read) { fds[0].events = fds[0].events | POLLIN; want_read = 0; } ret = poll(fds, 1, blocking ? 1000 : 0); if (ret == 0) { if (blocking) continue; return -1; } if (ret < 0 || fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { if (fds[0].revents & POLLERR) { debug(DBG_INFO, "sslwrite: socket error"); } else if (fds[0].revents & POLLHUP) { debug(DBG_INFO, "sslwrite: socket hang up"); } else if (fds[0].revents & POLLNVAL) { debug(DBG_ERR, "sslwrite: fd not open"); } return -1; } if ((ret = SSL_write(ssl, buf, num)) <= 0) { switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_WANT_READ: want_read = 1; case SSL_ERROR_WANT_WRITE: continue; default: while ((error = ERR_get_error())) debug(DBG_ERR, "sslwrite: SSL: %s", ERR_error_string(error, NULL)); } } break; } return ret; } /** * @brief read radius message from ssl session * * If errors are encountered (e.g. invalid message lengths) ssl session will be shut down) * All ssl operations will be performed with aquired lock. * Will allocate memory for buf. * * @param ssl SSL session to read from * @param timeout while reading. 0 means no timeout (blocking) * @param lock to aquire * @param buf newly allocated buffer containing the read bytes * @return int number of bytes read, 0 on timeout or error */ int radtlsget(SSL *ssl, int timeout, pthread_mutex_t *lock, uint8_t **buf) { int cnt, len; unsigned char init_buf[4]; cnt = sslreadtimeout(ssl, init_buf, 4, timeout, lock); if (cnt < 1) return 0; len = get_checked_rad_length(init_buf); if (len <= 0) { debug(DBG_ERR, "radtlsget: invalid message length (%d)! closing connection!", -len); pthread_mutex_lock(lock); SSL_shutdown(ssl); pthread_mutex_unlock(lock); return 0; } *buf = malloc(len); if (!*buf) { debug(DBG_ERR, "radtlsget: malloc failed! closing connection!"); pthread_mutex_lock(lock); SSL_shutdown(ssl); pthread_mutex_unlock(lock); return 0; } memcpy(*buf, init_buf, 4); cnt = sslreadtimeout(ssl, *buf + 4, len - 4, timeout, lock); if (cnt < 1) { debug(DBG_DBG, cnt ? "radtlsget: connection lost" : "radtlsget: timeout"); free(*buf); *buf = NULL; return 0; } debug(DBG_DBG, "radtlsget: got %d bytes", len); return len; } void *tlsserverwr(void *arg) { int cnt; struct client *client = (struct client *)arg; struct gqueue *replyq; struct request *reply; char tmp[INET6_ADDRSTRLEN]; struct timeval now; debug(DBG_DBG, "tlsserverwr: starting for %s", addr2string(client->addr, tmp, sizeof(tmp))); replyq = client->replyq; gettimeofday(&client->tlsnewkey, NULL); for (;;) { pthread_mutex_lock(&replyq->mutex); while (!list_first(replyq->entries)) { if (!SSL_get_shutdown(client->ssl)) { debug(DBG_DBG, "tlsserverwr: waiting for signal"); pthread_cond_wait(&replyq->cond, &replyq->mutex); debug(DBG_DBG, "tlsserverwr: got signal"); } else break; } reply = (struct request *)list_shift(replyq->entries); pthread_mutex_unlock(&replyq->mutex); pthread_mutex_lock(&client->lock); if (SSL_get_shutdown(client->ssl)) { if (reply) freerq(reply); pthread_mutex_unlock(&client->lock); debug(DBG_DBG, "tlsserverwr: ssl connection shutdown; exiting as requested"); pthread_exit(NULL); } gettimeofday(&now, NULL); #if OPENSSL_VERSION_NUMBER >= 0x10101000 if (now.tv_sec - client->tlsnewkey.tv_sec > RSP_TLS_REKEY_INTERVAL && SSL_version(client->ssl) >= TLS1_3_VERSION) { debug(DBG_DBG, "tlsserverwr: perform key update for long-running connection"); if (SSL_get_key_update_type(client->ssl) == SSL_KEY_UPDATE_NONE && !SSL_key_update(client->ssl, SSL_KEY_UPDATE_REQUESTED)) debug(DBG_WARN, "tlsserverwr: request for key update failed for %s", addr2string(client->addr, tmp, sizeof(tmp))); client->tlsnewkey = now; } #endif if ((cnt = sslwrite(client->ssl, reply->replybuf, reply->replybuflen, 1)) > 0) { debug(DBG_DBG, "tlsserverwr: sent %d bytes, Radius packet of length %d to %s", cnt, reply->replybuflen, addr2string(client->addr, tmp, sizeof(tmp))); } pthread_mutex_unlock(&client->lock); freerq(reply); } } /** * @brief server read-loop for SSL sessions * * Read radius messages from SSL session and call radsrv. * Write loop will be started implicitly * * @param client the calling client */ void tlsserverrd(struct client *client) { struct request *rq; uint8_t *buf = NULL; pthread_t tlsserverwrth; char tmp[INET6_ADDRSTRLEN]; int len = 0; debug(DBG_DBG, "tlsserverrd: starting for %s", addr2string(client->addr, tmp, sizeof(tmp))); if (pthread_create(&tlsserverwrth, &pthread_attr, tlsserverwr, (void *)client)) { debug(DBG_ERR, "tlsserverrd: pthread_create failed"); return; } for (;;) { len = radtlsget(client->ssl, IDLE_TIMEOUT * 3, &client->lock, &buf); if (!buf || !len) { pthread_mutex_lock(&client->lock); if (SSL_get_shutdown(client->ssl)) debug(DBG_ERR, "tlsserverrd: connection from %s, client %s lost", addr2string(client->addr, tmp, sizeof(tmp)), client->conf->name); else { debug(DBG_WARN, "tlsserverrd: timeout from %s, client %s (no requests), closing connection", addr2string(client->addr, tmp, sizeof(tmp)), client->conf->name); SSL_shutdown(client->ssl); } /* ensure shutdown state is set so tlsserverwr knows it can exit*/ SSL_set_shutdown(client->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); pthread_mutex_unlock(&client->lock); break; } debug(DBG_DBG, "tlsserverrd: got Radius message from %s", addr2string(client->addr, tmp, sizeof(tmp))); rq = newrequest(); if (!rq) { free(buf); buf = NULL; continue; } rq->buf = buf; rq->buflen = len; rq->from = client; if (!radsrv(rq)) { debug(DBG_ERR, "tlsserverrd: message authentication/validation failed, closing connection from %s", addr2string(client->addr, tmp, sizeof(tmp))); pthread_mutex_lock(&client->lock); SSL_shutdown(client->ssl); /* ensure shutdown state is set so tlsserverwr knows it can exit*/ SSL_set_shutdown(client->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); pthread_mutex_unlock(&client->lock); break; } buf = NULL; } /* signal writer so it can finish (based on SSL_shutdown) */ pthread_mutex_lock(&client->replyq->mutex); pthread_cond_signal(&client->replyq->cond); pthread_mutex_unlock(&client->replyq->mutex); debug(DBG_DBG, "tlsserverrd: waiting for writer to end"); pthread_join(tlsserverwrth, NULL); debug(DBG_DBG, "tlsserverrd: reader for %s exiting", addr2string(client->addr, tmp, sizeof(tmp))); } /** * @brief re-do certificate verification against (new) SSL_CTX * Caller must ensure thread-safety! * * @param ssl SSL connection object to verify * @param ssl_ctx SSL_CTX to verify against * @return int 1 if valid, 0 if invalid, -1 otherwise (not connected, no cert etc.) */ int reverifycert(SSL *ssl, SSL_CTX *ssl_ctx) { int result = -1; X509 *cert = NULL; STACK_OF(X509) *chain = NULL; X509_STORE *store = NULL; X509_STORE_CTX *ctx = NULL; char *buf = NULL; if (!ssl || !ssl_ctx) return result; if (!(store = SSL_CTX_get_cert_store(ssl_ctx))) return result; if (!SSL_is_init_finished(ssl) || SSL_get_shutdown(ssl) != 0) { debug(DBG_DBG, "reverifycert: SSL object not (yet) connected"); #if OPENSSL_VERSION_NUMBER >= 0x30000000 } else if (!(cert = SSL_get1_peer_certificate(ssl))) { #else } else if (!(cert = SSL_get_peer_certificate(ssl))) { #endif debug(DBG_DBG, "reverifycert: unable to get certificate from SSL object"); } else if (!SSL_get0_chain_certs(ssl, &chain)) { debug(DBG_DBG, "reverifycert: unable to get cert chain from SSL object"); } else if (!(ctx = X509_STORE_CTX_new())) { debug(DBG_ERR, "reverifycert: failed to create X509_STORE_CTX"); } else if (!X509_STORE_CTX_init(ctx, store, cert, chain)) { debug(DBG_ERR, "reverifycert: failed to init X509 store context"); } else { result = X509_verify_cert(ctx); buf = print_x509_name(X509_get_subject_name(X509_STORE_CTX_get_current_cert(ctx))); debug(result == 0 ? DBG_NOTICE : DBG_DBG, "reverify result: num=%d:%s:depth=%d:%s", X509_STORE_CTX_get_error(ctx), X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx)), X509_STORE_CTX_get_error_depth(ctx), buf ? buf : ""); free(buf); buf = NULL; } X509_STORE_CTX_free(ctx); X509_free(cert); return result; } /** * @brief re-validate server certificate and terminate connection if invalid * * @param srv server to validate */ void terminateinvalidserver(struct server *srv) { if (!srv) return; pthread_mutex_lock(&srv->lock); if (!srv->ssl || !srv->conf->tlsconf) { pthread_mutex_unlock(&srv->lock); return; } pthread_mutex_lock(&srv->conf->tlsconf->lock); switch (reverifycert(srv->ssl, tlsgetctx(srv->conf->type, srv->conf->tlsconf))) { case 0: debug(DBG_NOTICE, "terminateinvalidserver: certificate has become invalid, terminating connection to %s", srv->conf->name); SSL_shutdown(srv->ssl); break; case 1: debug(DBG_DBG, "terminateinvalidserver: certificate still valid for %s, continue", srv->conf->name); break; default: debug(DBG_DBG, "terminateinvalidserver: unable to determine certificate for %s, ignoring", srv->conf->name); } pthread_mutex_unlock(&srv->conf->tlsconf->lock); pthread_mutex_unlock(&srv->lock); } /** * @brief revalidate client certificate and terminate connection if invalid * * @param cli client to validate */ void terminateinvalidclient(struct client *cli) { char tmp[INET6_ADDRSTRLEN]; pthread_mutex_lock(&cli->lock); if (!cli->ssl || !cli->conf->tlsconf) { pthread_mutex_unlock(&cli->lock); return; } pthread_mutex_lock(&cli->conf->tlsconf->lock); switch (reverifycert(cli->ssl, tlsgetctx(cli->conf->type, cli->conf->tlsconf))) { case 0: debug(DBG_NOTICE, "terminateinvalidclient: certificate has become invalid, terminating connection from %s (%s)", cli->conf->name, addr2string(cli->addr, tmp, sizeof(tmp))); SSL_shutdown(cli->ssl); break; case 1: debug(DBG_DBG, "terminateinvalidclient: certificate still valid for %s (%s), continue", cli->conf->name, addr2string(cli->addr, tmp, sizeof(tmp))); break; default: debug(DBG_DBG, "terminateinvalidclient: unable to determine certificate for %s (%s), ignoring", cli->conf->name, addr2string(cli->addr, tmp, sizeof(tmp))); } pthread_mutex_unlock(&cli->conf->tlsconf->lock); pthread_mutex_unlock(&cli->lock); } #else /* Just to make the file non-empty, should rather avoid compiling this file when not needed */ typedef int make_compilers_happy; #endif /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/Makefile.am0000644000076600000240000000327014452772710011665 ## Copyright (c) 2006-2010, UNINETT AS ## Copyright (c) 2010-2012,2016, NORDUnet A/S ## See LICENSE for licensing information. AUTOMAKE_OPTIONS = foreign SUBDIRS = tests sbin_PROGRAMS = radsecproxy bin_PROGRAMS = radsecproxy-conf radsecproxy-hash noinst_LIBRARIES = librsp.a radsecproxy_SOURCES = main.c librsp_a_SOURCES = \ debug.c debug.h \ dns.c dns.h \ dtls.c dtls.h \ fticks.c fticks.h fticks_hashmac.c fticks_hashmac.h \ gconfig.c gconfig.h \ hash.c hash.h \ hostport.c hostport.h \ list.c list.h \ radmsg.c radmsg.h raddict.h \ radsecproxy.c radsecproxy.h \ rewrite.c rewrite.h \ tcp.c tcp.h \ tls.c tls.h \ tlscommon.c tlscommon.h \ tlv11.c tlv11.h \ udp.c udp.h \ util.c util.h radsecproxy_conf_SOURCES = \ catgconf.c \ debug.c debug.h \ gconfig.c gconfig.h \ util.c util.h #################### AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" AM_CFLAGS = \ -g -Wall -Werror -fno-strict-aliasing @OPENSSL_INCLUDES@ @TARGET_CFLAGS@ radsecproxy_LDFLAGS = @OPENSSL_LDFLAGS@ @TARGET_LDFLAGS@ radsecproxy_LDADD = librsp.a @OPENSSL_LIBS@ @LIBS@ radsecproxy_conf_LDFLAGS = @TARGET_LDFLAGS@ radsecproxy_hash_LDADD = fticks_hashmac.o hash.o list.o man_MANS = radsecproxy.8 radsecproxy-hash.8 radsecproxy.conf.5 EXTRA_DIST = \ LICENSE THANKS \ radsecproxy.conf-example \ tools/README tools/naptr-eduroam.sh tools/radsec-dynsrv.sh dist-sign: dist distcheck-sign: distcheck dist-sign distcheck-sign: gpg --armor --detach-sign $(DIST_ARCHIVES) distclean-local: rm -f @PACKAGE@-*.tar.gz rm -f @PACKAGE@-*.tar.gz.asc #################### html: radsecproxy.html radsecproxy-hash.html radsecproxy.conf.html %.html: %.8 groff -mandoc -Thtml $< >$@ %.html: %.5 groff -mandoc -Thtml $< >$@ radsecproxy-1.11.1/debug.c0000644000076600000240000001647614724607273011102 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2010-2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ #ifdef __linux__ #include #include #endif #include "debug.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include static char *debug_ident = NULL; static uint8_t debug_level = DBG_INFO; static char *debug_filepath = NULL; static FILE *debug_file = NULL; static int debug_syslogfacility = 0; static int fticks_syslogfacility = 0; static uint8_t debug_timestamp = 0; static uint8_t debug_tid = 0; void debug_init(char *ident) { debug_file = stderr; setvbuf(debug_file, NULL, _IONBF, 0); debug_ident = ident; } void debug_set_level(uint8_t level) { switch (level) { case 1: debug_level = DBG_ERR; return; case 2: debug_level = DBG_WARN; return; case 3: debug_level = DBG_NOTICE; return; case 4: debug_level = DBG_INFO; return; case 5: debug_level = DBG_DBG; return; } } void debug_timestamp_on(void) { debug_timestamp = 1; } void debug_tid_on(void) { debug_tid = 1; } uint8_t debug_get_level(void) { return debug_level; } int debug_set_destination(char *dest, int log_type) { static const char *facstrings[] = { "LOG_DAEMON", "LOG_MAIL", "LOG_USER", "LOG_LOCAL0", "LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7", NULL}; static const int facvals[] = { LOG_DAEMON, LOG_MAIL, LOG_USER, LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7}; int i; if (!strncasecmp(dest, "file:///", 8)) { if (log_type != LOG_TYPE_FTICKS) { debug_filepath = stringcopy(dest + 7, 0); debug_file = fopen(debug_filepath, "a"); if (!debug_file) debugx(1, DBG_ERR, "Failed to open logfile %s\n%s", debug_filepath, strerror(errno)); fclose(debug_file); debug_file = stderr; } else { debug(DBG_WARN, "FTicksSyslogFacility starting with file:/// not " "permitted, assuming default F-Ticks destination"); } return 1; } if (!strncasecmp(dest, "x-syslog://", 11) || log_type == LOG_TYPE_FTICKS) { if (!strncasecmp(dest, "x-syslog://", 11)) { dest += 11; if (*dest == '/') dest++; } if (*dest) { for (i = 0; facstrings[i]; i++) if (!strcasecmp(dest, facstrings[i])) break; if (!facstrings[i]) debugx(1, DBG_ERR, "Unknown syslog facility %s", dest); if (log_type != LOG_TYPE_FTICKS) debug_syslogfacility = facvals[i]; else if (log_type == LOG_TYPE_FTICKS) fticks_syslogfacility = facvals[i]; } else { if (log_type != LOG_TYPE_FTICKS) debug_syslogfacility = LOG_DAEMON; else if (log_type == LOG_TYPE_FTICKS) fticks_syslogfacility = 0; } openlog(debug_ident, LOG_PID, debug_syslogfacility); return 1; } debug(DBG_ERR, "Unknown log destination, exiting %s", dest); exit(1); } void debug_reopen_log(void) { if (!debug_filepath) return; if (debug_file != stderr) fclose(debug_file); debug_file = fopen(debug_filepath, "a"); if (!debug_file) { debug_file = stderr; debug(DBG_ERR, "Failed to open logfile %s, using stderr\n%s", debug_filepath, strerror(errno)); } setvbuf(debug_file, NULL, _IONBF, 0); } void debug_logit(uint8_t level, const char *format, va_list ap) { struct timeval now; char *timebuf = NULL, *tidbuf, *tmp = NULL, *tmp2 = NULL; int priority; size_t malloc_size; if (debug_tid) { #ifdef __linux__ pid_t tid = syscall(SYS_gettid); tidbuf = malloc(3 * sizeof(tid) + 1); sprintf(tidbuf, "%u", tid); #else pthread_t tid = pthread_self(); uint8_t *ptid = (uint8_t *)&tid; int i; tidbuf = malloc((2 * sizeof(tid) + 1)); tmp = tidbuf; for (i = sizeof(tid) - 1; i >= 0; i--) { tmp += sprintf(tmp, "%02x", ptid[i]); } #endif tmp = malloc(strlen(tidbuf) + strlen(format) + 4); sprintf(tmp, "(%s) %s", tidbuf, format); format = tmp; free(tidbuf); } if (debug_syslogfacility) { switch (level) { case DBG_DBG: priority = LOG_DEBUG; break; case DBG_INFO: priority = LOG_INFO; break; case DBG_NOTICE: priority = LOG_NOTICE; break; case DBG_WARN: priority = LOG_WARNING; break; case DBG_ERR: priority = LOG_ERR; break; default: priority = LOG_DEBUG; } vsyslog(priority, format, ap); } else { if (debug_timestamp && (timebuf = malloc(26 + 1))) { gettimeofday(&now, NULL); ctime_r(&now.tv_sec, timebuf); /*ctime_r writes exactly 24 bytes + "\n\0" */ strncpy(timebuf + 24, ": ", 3); } malloc_size = strlen(format) + (timebuf ? strlen(timebuf) : 0) + 2 * sizeof(char); tmp2 = malloc(malloc_size); if (tmp2) { snprintf(tmp2, malloc_size, "%s%s\n", timebuf ? timebuf : "", format); format = tmp2; } vfprintf(debug_file, format, ap); } free(tmp); free(tmp2); free(timebuf); } void debug(uint8_t level, char *format, ...) { va_list ap; if (level < debug_level) return; va_start(ap, format); debug_logit(level, format, ap); va_end(ap); } void debugx(int status, uint8_t level, char *format, ...) { if (level >= debug_level) { va_list ap; va_start(ap, format); debug_logit(level, format, ap); va_end(ap); } exit(status); } void debugerrno(int err, uint8_t level, char *format, ...) { if (level >= debug_level) { va_list ap; size_t len = strlen(format); char *tmp = malloc(len + 1024 + 2); assert(tmp); strcpy(tmp, format); tmp[len++] = ':'; tmp[len++] = ' '; va_start(ap, format); if (strerror_r(err, tmp + len, 1024)) debug_logit(level, format, ap); else debug_logit(level, tmp, ap); va_end(ap); free(tmp); } } void debugerrnox(int err, uint8_t level, char *format, ...) { if (level >= debug_level) { va_list ap; va_start(ap, format); debugerrno(err, level, format, ap); va_end(ap); } exit(err); } void fticks_debug(const char *format, ...) { int priority; va_list ap; va_start(ap, format); if (!debug_syslogfacility && !fticks_syslogfacility) debug_logit(0xff, format, ap); else { priority = LOG_DEBUG | fticks_syslogfacility; vsyslog(priority, format, ap); } va_end(ap); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/list.h0000644000076600000240000000247114722543325010755 /* Copyright (c) 2007,2009, UNINETT AS */ /* See LICENSE for licensing information. */ #ifndef _LIST_H #define _LIST_H #include struct list_node { struct list_node *next; void *data; }; struct list { struct list_node *first, *last; uint32_t count; }; /* allocates and initialises list structure; returns NULL if malloc fails */ struct list *list_create(void); /* frees all memory associated with the list */ void list_destroy(struct list *list); /* frees memory allocated for the list itself */ void list_free(struct list *list); /* appends entry to list; returns 1 if ok, 0 if malloc fails */ int list_push(struct list *list, void *data); /* insert entry at front of the list; returns 1 if ok, 0 if malloc fails */ int list_push_front(struct list *list, void *data); /* removes first entry from list and returns data */ void *list_shift(struct list *list); /* removes all entries with matching data pointer */ void list_removedata(struct list *list, void *data); /* returns first node */ struct list_node *list_first(struct list *list); /* returns the next node after the argument */ struct list_node *list_next(struct list_node *node); /* returns number of nodes */ uint32_t list_count(struct list *list); #endif /*_LIST_H*/ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/radsecproxy.h0000644000076600000240000001663514722543325012354 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2010-2012,2016, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #ifndef _RADSECPROXY_H #define _RADSECPROXY_H #include "gconfig.h" #include "hostport.h" #include "list.h" #include "radmsg.h" #include "rewrite.h" #include #include #include #include #include #include #define DEBUG_LEVEL 2 #define CONFIG_MAIN SYSCONFDIR "/radsecproxy.conf" /* MAX_REQUESTS must be 256 due to Radius' 8 bit ID field */ #define MAX_REQUESTS 256 #define MAX_LOSTRQS 16 #define REQUEST_RETRY_INTERVAL 5 #define REQUEST_RETRY_COUNT 2 #define DUPLICATE_INTERVAL REQUEST_RETRY_INTERVAL *REQUEST_RETRY_COUNT #define MAX_CERT_DEPTH 5 #define STATUS_SERVER_PERIOD 25 #define IDLE_TIMEOUT 300 #define PSK_MIN_LENGTH 16 #define RSP_SECRET_LEN_WARN 10 /* Older OpenSSL API had a 256 byte limit; keep this limit to maximize compatibility*/ #define PSK_ID_MAX_LENGTH 256 #define RSP_TLS_REKEY_INTERVAL 3600 /* Target value for stack size. * Some platforms might define higher minimums in PTHREAD_STACK_MIN. */ #define THREAD_STACK_SIZE 32768 /* For systems that only support RFC 2292 Socket API, but not RFC 3542 * like Cygwin */ #ifndef IPV6_RECVPKTINFO #define IPV6_RECVPKTINFO IPV6_PKTINFO #endif /* 27262 is vendor DANTE Ltd. */ #define DEFAULT_TTL_ATTR "27262:1" #define DEFAULT_FTICKS_PREFIX "F-TICKS/eduroam/1.0" #define RAD_UDP 0 #define RAD_TLS 1 #define RAD_TCP 2 #define RAD_DTLS 3 #define RAD_PROTOCOUNT 4 enum rsp_fticks_reporting_type { RSP_FTICKS_REPORTING_NONE = 0, /* Default. */ RSP_FTICKS_REPORTING_BASIC, RSP_FTICKS_REPORTING_FULL }; enum rsp_mac_type { RSP_MAC_STATIC = 0, RSP_MAC_ORIGINAL, RSP_MAC_VENDOR_HASHED, RSP_MAC_VENDOR_KEY_HASHED, /* Default. */ RSP_MAC_FULLY_HASHED, RSP_MAC_FULLY_KEY_HASHED }; enum rsp_server_state { RSP_SERVER_STATE_STARTUP = 0, /* default */ RSP_SERVER_STATE_BLOCKING_STARTUP, RSP_SERVER_STATE_CONNECTED, RSP_SERVER_STATE_RECONNECTING, RSP_SERVER_STATE_FAILING }; enum rsp_statsrv { RSP_STATSRV_OFF = 0, RSP_STATSRV_ON, RSP_STATSRV_MINIMAL, RSP_STATSRV_AUTO }; struct options { char *pidfile; char *logdestination; char *ftickssyslogfacility; char *fticksprefix; char *ttlattr; uint32_t ttlattrtype[2]; uint8_t addttl; uint8_t loglevel; uint8_t logtid; uint8_t logfullusername; uint8_t loopprevention; enum rsp_mac_type log_mac; uint8_t *log_key; enum rsp_fticks_reporting_type fticks_reporting; enum rsp_mac_type fticks_mac; uint8_t *fticks_key; uint8_t ipv4only; uint8_t ipv6only; uint8_t sni; uint8_t verifyeap; }; struct commonprotoopts { char **listenargs; char **sourcearg; }; struct request { struct timeval created; uint32_t refcount; pthread_mutex_t refmutex; uint8_t *buf, *replybuf; int buflen, replybuflen; struct radmsg *msg; struct client *from; struct server *to; char *origusername; uint8_t rqid; uint8_t rqauth[16]; uint8_t newid; int udpsock; /* only for UDP */ }; /* requests that our client will send */ struct rqout { pthread_mutex_t *lock; struct request *rq; uint8_t tries; struct timeval expiry; }; struct gqueue { struct list *entries; pthread_mutex_t mutex; pthread_cond_t cond; }; struct clsrvconf { uint8_t shallow; struct clsrvconf *parent; char *name; uint8_t type; /* RAD_UDP/RAD_TLS/RAD_TCP */ const struct protodefs *pdef; char **hostsrc; char *servername; int hostaf; char *portsrc; struct list *hostports; char **source; uint8_t *secret; int secret_len; char *tls; char *pskid; uint8_t *pskkey; int pskkeylen; struct list *matchcertattrs; char **confmatchcertattrs; char *confrewritein; char *confrewriteout; char *confrewriteusername; struct modattr *rewriteusername; char *dynamiclookupcommand; enum rsp_statsrv statusserver; uint8_t retryinterval; uint8_t retrycount; uint8_t dupinterval; uint8_t certnamecheck; uint8_t addttl; uint8_t keepalive; uint8_t loopprevention; uint8_t blockingstartup; struct rewrite *rewritein; struct rewrite *rewriteout; pthread_mutex_t *lock; /* only used for updating clients so far */ struct tls *tlsconf; struct list *clients; struct server *servers; char *fticks_viscountry; char *fticks_visinst; uint8_t sni; char *sniservername; long dtlsmtu; uint8_t reqmsgauth; uint8_t reqmsgauthproxy; }; #include "tlscommon.h" struct client { struct clsrvconf *conf; int sock; SSL *ssl; pthread_mutex_t lock; struct request *rqs[MAX_REQUESTS]; struct gqueue *replyq; struct sockaddr *addr; time_t expiry; /* for udp */ struct timeval tlsnewkey; }; struct server { struct clsrvconf *conf; int sock; SSL *ssl; pthread_mutex_t lock; pthread_t clientth; uint8_t clientrdgone; struct timeval connecttime; struct timeval lastreply; struct timeval tlsnewkey; enum rsp_server_state state; uint8_t lostrqs; char *dynamiclookuparg; int nextid; struct timeval lastrcv; struct rqout *requests; uint8_t newrq; uint8_t conreset; pthread_mutex_t newrq_mutex; pthread_cond_t newrq_cond; }; struct realm { char *name; char *message; uint8_t accresp; uint8_t acclog; regex_t regex; uint32_t refcount; pthread_mutex_t refmutex; pthread_mutex_t mutex; struct realm *parent; struct list *subrealms; struct list *srvconfs; struct list *accsrvconfs; }; struct protodefs { char *name; char *secretdefault; int socktype; char *portdefault; uint8_t retrycountdefault; uint8_t retrycountmax; uint8_t retryintervaldefault; uint8_t retryintervalmax; uint8_t duplicateintervaldefault; void (*setprotoopts)(struct commonprotoopts *); char **(*getlistenerargs)(void); void *(*listener)(void *); int (*connecter)(struct server *, int, int); void *(*clientconnreader)(void *); int (*clientradput)(struct server *, unsigned char *, int); void (*addclient)(struct client *); void (*addserverextra)(struct clsrvconf *); void (*setsrcres)(void); void (*initextra)(void); }; struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur, struct hostportres **hp); struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur); struct list *find_all_clconf(uint8_t type, struct sockaddr *addr, struct list_node *cur, struct hostportres **hp); struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur); struct client *addclient(struct clsrvconf *conf, uint8_t lock); void removelockedclient(struct client *client); void removeclient(struct client *client); struct gqueue *newqueue(void); struct request *newrequest(void); void freerq(struct request *rq); int radsrv(struct request *rq); int timeouth(struct server *server); int closeh(struct server *server); int replyh(struct server *server, uint8_t *buf, int buflen); struct addrinfo *resolve_hostport_addrinfo(uint8_t type, char *hostport); uint8_t *radattr2ascii(struct tlv *attr); /* TODO: mv this to radmsg? */ extern pthread_attr_t pthread_attr; #endif /* _RADSECPROXY_H */ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/tcp.c0000644000076600000240000003334714722543325010571 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2012, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include #include #include #include #include #include #include #ifdef SYS_SOLARIS #include #endif #include "hostport.h" #include "list.h" #include "radsecproxy.h" #include #include #include #include #include #include #include #include #ifdef RADPROT_TCP #include "debug.h" #include "util.h" static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(void); void *tcplistener(void *arg); int tcpconnect(struct server *server, int timeout, int reconnect); void *tcpclientrd(void *arg); int clientradputtcp(struct server *server, unsigned char *rad, int radlen); void tcpsetsrcres(void); static const struct protodefs protodefs = { "tcp", NULL, /* secretdefault */ SOCK_STREAM, /* socktype */ "1812", /* portdefault */ 0, /* retrycountdefault */ 0, /* retrycountmax */ REQUEST_RETRY_INTERVAL *REQUEST_RETRY_COUNT, /* retryintervaldefault */ 60, /* retryintervalmax */ DUPLICATE_INTERVAL, /* duplicateintervaldefault */ setprotoopts, /* setprotoopts */ getlistenerargs, /* getlistenerargs */ tcplistener, /* listener */ tcpconnect, /* connecter */ tcpclientrd, /* clientconnreader */ clientradputtcp, /* clientradput */ NULL, /* addclient */ NULL, /* addserverextra */ tcpsetsrcres, /* setsrcres */ NULL /* initextra */ }; static struct addrinfo *srcres = NULL; static uint8_t handle; static struct commonprotoopts *protoopts = NULL; const struct protodefs *tcpinit(uint8_t h) { handle = h; return &protodefs; } static void setprotoopts(struct commonprotoopts *opts) { protoopts = opts; } static char **getlistenerargs(void) { return protoopts ? protoopts->listenargs : NULL; } void tcpsetsrcres(void) { if (!srcres) srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, AF_UNSPEC, NULL, protodefs.socktype); } int tcpconnect(struct server *server, int timeout, int reconnect) { struct timeval now, start; int firsttry = 1; uint32_t wait; struct addrinfo *source = NULL; struct list_node *entry; struct hostportres *hp; debug(DBG_DBG, "tcpconnect: %s to %s", reconnect ? "reconnecting" : "initial connection", server->conf->name); pthread_mutex_lock(&server->lock); if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; pthread_mutex_unlock(&server->lock); if (server->conf->source) { source = resolvepassiveaddrinfo(server->conf->source, AF_UNSPEC, NULL, protodefs.socktype); if (!source) debug(DBG_WARN, "tcpconnect: could not resolve source address to bind for server %s, using default", server->conf->name); } gettimeofday(&start, NULL); for (;;) { if (server->sock >= 0) close(server->sock); server->sock = -1; wait = connect_wait(start, server->connecttime, firsttry); gettimeofday(&now, NULL); if (timeout && (now.tv_sec - start.tv_sec) + wait > timeout) { debug(DBG_DBG, "tcpconnect: timeout"); if (source) freeaddrinfo(source); return 0; } if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); sleep(wait); firsttry = 0; for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_INFO, "tcpconnect: trying to open TCP connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port); if ((server->sock = connecttcp(hp->addrinfo, source ? source : srcres, list_count(server->conf->hostports) > 1 ? 5 : 30)) >= 0) { debug(DBG_WARN, "tcpconnect: TCP connection to server %s (%s port %s) up", server->conf->name, hp->host, hp->port); break; } } if (server->sock < 0) { debug(DBG_ERR, "tcpconnect: TCP connection to server %s failed", server->conf->name); continue; } if (server->conf->keepalive) enable_keepalive(server->sock); break; } gettimeofday(&server->connecttime, NULL); pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); server->conreset = reconnect; pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); if (source) freeaddrinfo(source); return 1; } /* timeout in seconds, 0 means no timeout (blocking), returns when num bytes have been read, or timeout */ /* returns 0 on timeout, -1 on error and num if ok */ int tcpreadtimeout(int s, unsigned char *buf, int num, int timeout) { int ndesc, cnt, len; struct pollfd fds[1]; if (s < 0) return -1; /* make socket non-blocking? */ for (len = 0; len < num; len += cnt) { fds[0].fd = s; fds[0].events = POLLIN; ndesc = poll(fds, 1, timeout ? timeout * 1000 : -1); if (ndesc < 1) return ndesc; if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { return -1; } cnt = read(s, buf + len, num - len); if (cnt <= 0) return -1; } return num; } /* timeout in seconds, 0 means no timeout (blocking) return 0 on timeout, <0 on error */ int radtcpget(int s, int timeout, uint8_t **buf) { int cnt, len; unsigned char init_buf[4]; cnt = tcpreadtimeout(s, init_buf, 4, timeout); if (cnt < 1) { debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout"); return cnt; } len = get_checked_rad_length(init_buf); if (len <= 0) { debug(DBG_ERR, "radtcpget: invalid message length (%d)! closing connection!", -len); return len; } *buf = malloc(len); if (!*buf) { debug(DBG_ERR, "radtcpget: malloc failed! closing connection!"); return -1; } memcpy(*buf, init_buf, 4); cnt = tcpreadtimeout(s, *buf + 4, len - 4, timeout); if (cnt < 1) { debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout"); free(*buf); *buf = NULL; return cnt; } debug(DBG_DBG, "radtcpget: got %d bytes", len); return len; } int clientradputtcp(struct server *server, unsigned char *rad, int radlen) { int cnt; struct clsrvconf *conf = server->conf; if (radlen <= 0) { debug(DBG_ERR, "clientradputtcp: invalid buffer (length)"); return 0; } pthread_mutex_lock(&server->lock); if (server->state != RSP_SERVER_STATE_CONNECTED) { pthread_mutex_unlock(&server->lock); return 0; } if ((cnt = write(server->sock, rad, radlen)) <= 0) { debug(DBG_ERR, "clientradputtcp: write error"); pthread_mutex_unlock(&server->lock); return 0; } debug(DBG_DBG, "clientradputtcp: Sent %d bytes, Radius packet of length %zu to TCP peer %s", cnt, radlen, conf->name); pthread_mutex_unlock(&server->lock); return 1; } void *tcpclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; int len = 0; for (;;) { len = radtcpget(server->sock, server->conf->retryinterval * (server->conf->retrycount + 1), &buf); if (buf && len > 0) { if (!replyh(server, buf, len)) if (closeh(server)) break; buf = NULL; } else if (len == 0) { if (timeouth(server)) break; } else { if (closeh(server)) break; } } shutdown(server->sock, SHUT_RDWR); close(server->sock); server->clientrdgone = 1; pthread_mutex_lock(&server->newrq_mutex); pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); return NULL; } void *tcpserverwr(void *arg) { int cnt; struct client *client = (struct client *)arg; struct gqueue *replyq; struct request *reply; char tmp[INET6_ADDRSTRLEN]; debug(DBG_DBG, "tcpserverwr: starting for %s", addr2string(client->addr, tmp, sizeof(tmp))); replyq = client->replyq; for (;;) { pthread_mutex_lock(&replyq->mutex); while (!list_first(replyq->entries)) { if (client->sock >= 0) { debug(DBG_DBG, "tcpserverwr: waiting for signal"); pthread_cond_wait(&replyq->cond, &replyq->mutex); debug(DBG_DBG, "tcpserverwr: got signal"); } if (client->sock < 0) { /* s might have changed while waiting */ pthread_mutex_unlock(&replyq->mutex); debug(DBG_DBG, "tcpserverwr: exiting as requested"); pthread_exit(NULL); } } reply = (struct request *)list_shift(replyq->entries); pthread_mutex_unlock(&replyq->mutex); cnt = write(client->sock, reply->replybuf, reply->replybuflen); if (cnt > 0) debug(DBG_DBG, "tcpserverwr: sent %d bytes, Radius packet of length %d to %s", cnt, reply->replybuflen, addr2string(client->addr, tmp, sizeof(tmp))); else debug(DBG_ERR, "tcpserverwr: write error for %s", addr2string(client->addr, tmp, sizeof(tmp))); freerq(reply); } } void tcpserverrd(struct client *client) { struct request *rq; uint8_t *buf = NULL; pthread_t tcpserverwrth; char tmp[INET6_ADDRSTRLEN]; int len = 0; debug(DBG_DBG, "tcpserverrd: starting for %s", addr2string(client->addr, tmp, sizeof(tmp))); if (pthread_create(&tcpserverwrth, &pthread_attr, tcpserverwr, (void *)client)) { debug(DBG_ERR, "tcpserverrd: pthread_create failed"); return; } for (;;) { len = radtcpget(client->sock, 0, &buf); if (!buf || !len) { debug(DBG_ERR, "tcpserverrd: connection from %s lost", addr2string(client->addr, tmp, sizeof(tmp))); break; } debug(DBG_DBG, "tcpserverrd: got Radius message from %s", addr2string(client->addr, tmp, sizeof(tmp))); rq = newrequest(); if (!rq) { free(buf); buf = NULL; continue; } rq->buf = buf; rq->buflen = len; rq->from = client; if (!radsrv(rq)) { debug(DBG_ERR, "tcpserverrd: message authentication/validation failed, closing connection from %s", addr2string(client->addr, tmp, sizeof(tmp))); break; } buf = NULL; } /* stop writer by setting s to -1 and give signal in case waiting for data */ client->sock = -1; pthread_mutex_lock(&client->replyq->mutex); pthread_cond_signal(&client->replyq->cond); pthread_mutex_unlock(&client->replyq->mutex); debug(DBG_DBG, "tcpserverrd: waiting for writer to end"); pthread_join(tcpserverwrth, NULL); debug(DBG_DBG, "tcpserverrd: reader for %s exiting", addr2string(client->addr, tmp, sizeof(tmp))); } void *tcpservernew(void *arg) { int s; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); struct clsrvconf *conf; struct client *client; char tmp[INET6_ADDRSTRLEN]; s = *(int *)arg; free(arg); if (getpeername(s, (struct sockaddr *)&from, &fromlen)) { debug(DBG_DBG, "tcpservernew: getpeername failed, exiting"); goto exit; } debug(DBG_WARN, "tcpservernew: incoming TCP connection from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); conf = find_clconf(handle, (struct sockaddr *)&from, NULL, NULL); if (conf) { client = addclient(conf, 1); if (client) { if (conf->keepalive) enable_keepalive(s); client->sock = s; client->addr = addr_copy((struct sockaddr *)&from); tcpserverrd(client); removeclient(client); } else debug(DBG_WARN, "tcpservernew: failed to create new client instance"); } else debug(DBG_WARN, "tcpservernew: ignoring request, no matching TCP client"); exit: shutdown(s, SHUT_RDWR); close(s); pthread_exit(NULL); } void tcpaccept(int s) { int *s_arg; pthread_t tcpserverth; s_arg = malloc(sizeof(s)); if (!s_arg) { debug(DBG_ERR, "tcpaccept: malloc failed"); return; } *s_arg = s; if (pthread_create(&tcpserverth, &pthread_attr, tcpservernew, (void *)s_arg)) { debug(DBG_ERR, "tcpaccept: pthread_create failed"); free(s_arg); shutdown(s, SHUT_RDWR); close(s); return; } pthread_detach(tcpserverth); } void *tcplistener(void *arg) { accepttcp(*(int *)arg, tcpaccept); free(arg); return NULL; } #else const struct protodefs *tcpinit(uint8_t h) { return NULL; } #endif /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/fticks_hashmac.c0000644000076600000240000000647214722543325012751 /* Copyright (c) 2011,2013, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "fticks_hashmac.h" #include #include #include #include #include #include #include /** \a HASH is an input buffer of length SHA256_DIGEST_SIZE bytes. \a OUT_LEN is the size in bytes of \OUT. \a OUT is an output buffer of length \a OUT_LEN. */ static void _format_hash(const uint8_t *hash, size_t out_len, uint8_t *out) { int ir, iw; if (out_len < 3) { memset(out, 0, out_len); return; } for (ir = 0, iw = 0; iw <= out_len - 3; ir++, iw += 2) sprintf((char *)out + iw, "%02x", hash[ir % SHA256_DIGEST_SIZE]); } static void _hash(const uint8_t *in, const uint8_t *key, size_t out_len, uint8_t *out) { if (key == NULL) { struct sha256_ctx ctx; uint8_t hash[SHA256_DIGEST_SIZE]; sha256_init(&ctx); sha256_update(&ctx, strlen((char *)in), in); sha256_digest(&ctx, sizeof(hash), hash); _format_hash(hash, out_len, out); } else { struct hmac_sha256_ctx ctx; uint8_t hash[SHA256_DIGEST_SIZE]; hmac_sha256_set_key(&ctx, strlen((char *)key), key); hmac_sha256_update(&ctx, strlen((char *)in), in); hmac_sha256_digest(&ctx, sizeof(hash), hash); _format_hash(hash, out_len, out); } } /** Hash the Ethernet MAC address in \a IN, keying a HMAC with \a KEY unless \a KEY is NULL. If \a KEY is null \a IN is hashed with an ordinary cryptographic hash function such as SHA-2. \a IN and \a KEY are NUL terminated strings. \a IN is supposed to be an Ethernet MAC address and is sanitised by lowercasing it, removing all but [0-9a-f] and truncating it at the first ';' found. The truncation is done because RADIUS supposedly has a praxis of tacking on SSID to the MAC address in Calling-Station-Id. The resulting hash value is written to \a OUT as a NUL terminated string of numbers in two-digit hexadecimal ASCII representation. Exactly \a OUT_LEN bytes are written to \a OUT, based on the first (\a OUT_LEN - 1) / 2 bytes of the hash. Note that in the case when \OUT_LEN - 1 is more than two times the length of the hash, the output is repeated by concatinating another hex ASCII representation of the hash to the output until the buffer is full. \return 0 on success, -ENOMEM on out of memory. */ int fticks_hashmac(const uint8_t *in, const uint8_t *key, size_t out_len, uint8_t *out) { uint8_t *in_copy = NULL; uint8_t *p = NULL; int i; in_copy = calloc(1, strlen((const char *)in) + 1); if (in_copy == NULL) return -ENOMEM; /* Sanitise and lowercase 'in' into 'in_copy'. */ for (i = 0, p = in_copy; in[i] != '\0'; i++) { if (in[i] == ';') { *p++ = '\0'; break; } if (in[i] >= '0' && in[i] <= '9') { *p++ = in[i]; } else if (tolower(in[i]) >= 'a' && tolower(in[i]) <= 'f') { *p++ = tolower(in[i]); } } _hash(in_copy, key, out_len, out); free(in_copy); return 0; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/rewrite.h0000644000076600000240000000244714722543325011466 /* Copyright (c) 2019, SWITCH */ /* See LICENSE for licensing information. */ #ifndef _REWRITE_H #define _REWRITE_H #include "list.h" #include "radmsg.h" #include struct modattr { uint8_t t; uint32_t vendor; char *replacement; regex_t *regex; }; struct rewrite { uint8_t whitelist_mode; uint8_t *removeattrs; /*NULL terminated*/ uint32_t *removevendorattrs; /*NULL terminated*/ struct list *addattrs; /*struct tlv*/ struct list *modattrs; /*struct modattr*/ struct list *modvattrs; /*struct modattr*/ struct list *supattrs; /*struct tlv*/ }; void addrewrite(char *value, uint8_t whitelist_mode, char **rmattrs, char **rmvattrs, char **addattrs, char **addvattrs, char **modattrs, char **modvattrs, char **supattrs, char **supvattrs); int dorewrite(struct radmsg *msg, struct rewrite *rewrite); struct modattr *extractmodattr(char *nameval); struct rewrite *getrewrite(char *alt1, char *alt2); int dorewritemodattr(struct tlv *attr, struct modattr *modattr); void dorewriterm(struct radmsg *msg, uint8_t *rmattrs, uint32_t *rmvattrs, int inverted); int addvendorattr(struct radmsg *msg, uint32_t vendor, struct tlv *attr); #endif /*_REWRITE_H*/ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/main.c0000644000076600000240000000042414722543325010715 /* Copyright (c) 2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ int radsecproxy_main(int argc, char **argv); int main(int argc, char **argv) { return radsecproxy_main(argc, argv); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/NEWS0000644000076600000240000000001714715040746010323 See ChangeLog. radsecproxy-1.11.1/hostport.h0000644000076600000240000000232214722543325011657 /* Copyright (c) 2009, UNINETT AS * Copyright (c) 2012, NORDUnet A/S */ /* See LICENSE for licensing information. */ #ifndef _HOSTPORT_H #define _HOSTPORT_H #include "list.h" #include struct hostportres { char *host; char *port; uint8_t prefixlen; struct addrinfo *addrinfo; }; struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok); int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok); void freehostport(struct hostportres *hp); void freehostports(struct list *hostports); int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passive); int resolvehostports(struct list *hostports, int af, int socktype); struct addrinfo *resolvepassiveaddrinfo(char **hostport, int af, char *default_port, int socktype); int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t checkport); int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport, struct hostportres **hp); int connecttcphostlist(struct list *hostports, struct addrinfo *src, struct hostportres **hpreturn); #endif /* _HOSTPORT_H */ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/util.h0000644000076600000240000000243414722543325010756 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2016-2017, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include #include #include #define SOCKADDR_SIZE(addr) ((addr).ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) #define SOCKADDRP_SIZE(addr) ((addr)->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) char *stringcopy(const char *s, int len); int verifyutf8(const unsigned char *str, size_t str_len); const char *addr2string(struct sockaddr *addr, char *buf, size_t len); struct sockaddr *addr_copy(struct sockaddr *in); void port_set(struct sockaddr *sa, uint16_t port); void sock_dgram_skip(int socket); void printfchars(char *prefixfmt, char *prefix, char *charfmt, uint8_t *chars, int len); void disable_DF_bit(int socket, struct addrinfo *res); void enable_keepalive(int socket); int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse); int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout); void accepttcp(int socket, void handler(int)); uint32_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/tls.c0000644000076600000240000004302114722543325010573 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2012, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "debug.h" #include "hostport.h" #include "radsecproxy.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RADPROT_TLS static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(void); void *tlslistener(void *arg); int tlsconnect(struct server *server, int timeout, int reconnect); void *tlsclientrd(void *arg); int clientradputtls(struct server *server, unsigned char *rad, int radlen); void tlssetsrcres(void); static const struct protodefs protodefs = { "tls", "radsec", /* secretdefault */ SOCK_STREAM, /* socktype */ "2083", /* portdefault */ 0, /* retrycountdefault */ 0, /* retrycountmax */ REQUEST_RETRY_INTERVAL *REQUEST_RETRY_COUNT, /* retryintervaldefault */ 60, /* retryintervalmax */ DUPLICATE_INTERVAL, /* duplicateintervaldefault */ setprotoopts, /* setprotoopts */ getlistenerargs, /* getlistenerargs */ tlslistener, /* listener */ tlsconnect, /* connecter */ tlsclientrd, /* clientconnreader */ clientradputtls, /* clientradput */ NULL, /* addclient */ NULL, /* addserverextra */ tlssetsrcres, /* setsrcres */ NULL /* initextra */ }; static struct addrinfo *srcres = NULL; static uint8_t handle; static struct commonprotoopts *protoopts = NULL; const struct protodefs *tlsinit(uint8_t h) { handle = h; return &protodefs; } static void setprotoopts(struct commonprotoopts *opts) { protoopts = opts; } static char **getlistenerargs(void) { return protoopts ? protoopts->listenargs : NULL; } void tlssetsrcres(void) { if (!srcres) srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, AF_UNSPEC, NULL, protodefs.socktype); } static void cleanup_connection(struct server *server) { if (server->ssl) SSL_shutdown(server->ssl); if (server->sock >= 0) close(server->sock); server->sock = -1; if (server->ssl) SSL_free(server->ssl); server->ssl = NULL; } int tlsconnect(struct server *server, int timeout, int reconnect) { struct timeval now, start; uint32_t wait; int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; unsigned long error; int origflags; struct addrinfo *source = NULL; char *subj; struct list_node *entry; struct hostportres *hp; debug(DBG_DBG, "tlsconnect: %s to %s", reconnect ? "reconnecting" : "initial connection", server->conf->name); pthread_mutex_lock(&server->lock); if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; pthread_mutex_unlock(&server->lock); if (server->conf->source) { source = resolvepassiveaddrinfo(server->conf->source, AF_UNSPEC, NULL, protodefs.socktype); if (!source) debug(DBG_WARN, "tlsconnect: could not resolve source address to bind for server %s, using default", server->conf->name); } gettimeofday(&start, NULL); for (;;) { cleanup_connection(server); wait = connect_wait(start, server->connecttime, firsttry); gettimeofday(&now, NULL); if (timeout && (now.tv_sec - start.tv_sec) + wait > timeout) { debug(DBG_DBG, "tlsconnect: timeout"); if (source) freeaddrinfo(source); return 0; } if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); sleep(wait); firsttry = 0; gettimeofday(&now, NULL); if (timeout && (now.tv_sec - start.tv_sec) > timeout) { debug(DBG_DBG, "tlsconnect: timeout"); if (source) freeaddrinfo(source); return 0; } for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_INFO, "tlsconnect: trying to open TLS connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port); if ((server->sock = connecttcp(hp->addrinfo, source ? source : srcres, list_count(server->conf->hostports) > 1 ? 5 : 30)) < 0) { debug(DBG_ERR, "tlsconnect: TLS connection to %s (%s port %s) failed: TCP connect failed", server->conf->name, hp->host, hp->port); goto concleanup; } if (server->conf->keepalive) enable_keepalive(server->sock); pthread_mutex_lock(&server->conf->tlsconf->lock); if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))) { pthread_mutex_unlock(&server->conf->tlsconf->lock); debug(DBG_ERR, "tlsconnect: failed to get TLS context for server %s", server->conf->name); goto concleanup; } server->ssl = SSL_new(ctx); pthread_mutex_unlock(&server->conf->tlsconf->lock); if (!server->ssl) { debug(DBG_ERR, "tlsconnect: failed to create SSL connection for server %s", server->conf->name); goto concleanup; } if (!SSL_set_ex_data(server->ssl, RSP_EX_DATA_CONFIG, server->conf)) { debug(DBG_WARN, "tlsconnect: failed to set ex data"); } if (server->conf->sni) { struct in6_addr tmp; char *servername = server->conf->sniservername ? server->conf->sniservername : server->conf->servername ? server->conf->servername : (inet_pton(AF_INET, hp->host, &tmp) || inet_pton(AF_INET6, hp->host, &tmp)) ? NULL : hp->host; if (servername && !tlssetsni(server->ssl, servername)) { debug(DBG_ERR, "tlsconnect: set SNI %s failed", servername); goto concleanup; } } SSL_set_fd(server->ssl, server->sock); if (sslconnecttimeout(server->ssl, 5) <= 0) { while ((error = ERR_get_error())) debug(DBG_ERR, "tlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL)); debug(DBG_ERR, "tlsconnect: SSL connect to %s (%s port %s) failed", server->conf->name, hp->host, hp->port); goto concleanup; } if (server->conf->pskid && server->conf->pskkey) { if (SSL_session_reused(server->ssl)) { debug(DBG_WARN, "tlsconnect: TLS connection to %s (%s port %s), PSK identity %s with cipher %s up", server->conf->name, hp->host, hp->port, server->conf->pskid, SSL_CIPHER_get_name(SSL_get_current_cipher(server->ssl))); break; } else { debug(DBG_ERR, "tlsconnect: TLS PSK set for %s (%s port %s) but not used in session, rejecting connection", server->conf->name, hp->host, hp->port); goto concleanup; } } cert = verifytlscert(server->ssl); if (!cert) { debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port); goto concleanup; } if (verifyconfcert(cert, server->conf, hp)) { subj = getcertsubject(cert); if (subj) { debug(DBG_WARN, "tlsconnect: TLS connection to %s (%s port %s), subject %s, %s with cipher %s up", server->conf->name, hp->host, hp->port, subj, SSL_get_version(server->ssl), SSL_CIPHER_get_name(SSL_get_current_cipher(server->ssl))); free(subj); } X509_free(cert); break; } else { debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port); } X509_free(cert); concleanup: /* ensure previous connection is properly closed */ cleanup_connection(server); } if (server->ssl) break; } gettimeofday(&server->connecttime, NULL); server->tlsnewkey = server->connecttime; origflags = fcntl(server->sock, F_GETFL, 0); if (origflags == -1) { debugerrno(errno, DBG_WARN, "Failed to get flags"); } else if (fcntl(server->sock, F_SETFL, origflags | O_NONBLOCK) == -1) { debugerrno(errno, DBG_WARN, "Failed to set O_NONBLOCK"); } pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); server->conreset = reconnect; pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); if (source) freeaddrinfo(source); return 1; } int clientradputtls(struct server *server, unsigned char *rad, int radlen) { int cnt; struct clsrvconf *conf = server->conf; struct timeval now; if (radlen <= 0) { debug(DBG_ERR, "clientradputtls: invalid buffer (length)"); return 0; } pthread_mutex_lock(&server->lock); if (server->state != RSP_SERVER_STATE_CONNECTED) { pthread_mutex_unlock(&server->lock); return 0; } gettimeofday(&now, NULL); #if OPENSSL_VERSION_NUMBER >= 0x10101000 if (now.tv_sec - server->tlsnewkey.tv_sec > RSP_TLS_REKEY_INTERVAL && SSL_version(server->ssl) >= TLS1_3_VERSION) { debug(DBG_DBG, "clientradputtls: perform key update for long-running connection"); if (SSL_get_key_update_type(server->ssl) == SSL_KEY_UPDATE_NONE && !SSL_key_update(server->ssl, SSL_KEY_UPDATE_REQUESTED)) debug(DBG_WARN, "clientradputtls: request for key update failed for %s", conf->name); server->tlsnewkey = now; } #endif if ((cnt = sslwrite(server->ssl, rad, radlen, 0)) <= 0) { pthread_mutex_unlock(&server->lock); return 0; } debug(DBG_DBG, "clientradputtls: Sent %d bytes, Radius packet of length %zu to TLS peer %s", cnt, radlen, conf->name); pthread_mutex_unlock(&server->lock); return 1; } void *tlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf = NULL; int len = 0; for (;;) { len = radtlsget(server->ssl, server->conf->retryinterval * (server->conf->retrycount + 1), &server->lock, &buf); if (buf && len > 0) { if (!replyh(server, buf, len)) if (closeh(server)) break; buf = NULL; } else if (SSL_get_shutdown(server->ssl)) { if (closeh(server)) break; } else { if (timeouth(server)) break; } } debug(DBG_INFO, "tlsclientrd: exiting for %s", server->conf->name); pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_FAILING; SSL_shutdown(server->ssl); shutdown(server->sock, SHUT_RDWR); close(server->sock); /* Wake up clientwr(). */ server->clientrdgone = 1; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); return NULL; } void *tlsservernew(void *arg) { int s, origflags; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); struct clsrvconf *conf; struct list_node *cur = NULL; SSL *ssl = NULL; X509 *cert = NULL; SSL_CTX *ctx = NULL; unsigned long error; struct client *client; struct tls *accepted_tls = NULL; char tmp[INET6_ADDRSTRLEN], *subj; struct hostportres *hp; s = *(int *)arg; free(arg); if (getpeername(s, (struct sockaddr *)&from, &fromlen)) { debug(DBG_DBG, "tlsservernew: getpeername failed, exiting"); goto exit; } debug(DBG_WARN, "tlsservernew: incoming TLS connection from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); if (!(conf = find_clconf(handle, (struct sockaddr *)&from, &cur, &hp))) { debug(DBG_WARN, "tlsservernew: ignoring unknown TLS client %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); goto exit; } pthread_mutex_lock(&conf->tlsconf->lock); ctx = tlsgetctx(handle, conf->tlsconf); if (!ctx) { pthread_mutex_unlock(&conf->tlsconf->lock); goto exit; } ssl = SSL_new(ctx); pthread_mutex_unlock(&conf->tlsconf->lock); if (!ssl) goto exit; if (!SSL_set_ex_data(ssl, RSP_EX_DATA_CONFIG_LIST, find_all_clconf(handle, (struct sockaddr *)&from, cur, &hp))) { debug(DBG_WARN, "tlsservernew: failed to set ex data"); } SSL_set_fd(ssl, s); if (sslaccepttimeout(ssl, 30) <= 0) { struct clsrvconf *selected = SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG); conf = selected ? selected : conf; while ((error = ERR_get_error())) debug(DBG_ERR, "tlsservernew: SSL accept from %s (%s) failed: %s", conf->name, addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)), ERR_error_string(error, NULL)); debug(DBG_ERR, "tlsservernew: SSL_accept failed"); list_free(SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG_LIST)); goto exit; } list_free(SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG_LIST)); if (!(SSL_session_reused(ssl) || (cert = verifytlscert(ssl)))) goto exit; { struct clsrvconf *selected = SSL_get_ex_data(ssl, RSP_EX_DATA_CONFIG); conf = selected ? selected : conf; } accepted_tls = conf->tlsconf; origflags = fcntl(s, F_GETFL, 0); if (origflags == -1) { debugerrno(errno, DBG_WARN, "Failed to get flags"); } else if (fcntl(s, F_SETFL, origflags | O_NONBLOCK) == -1) { debugerrno(errno, DBG_WARN, "Failed to set O_NONBLOCK"); } if (SSL_session_reused(ssl)) { debug(DBG_WARN, "tlsservernew: TLS connection from %s, client %s, PSK identity %s wtih cipher %s up", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)), conf->name, conf->pskid, SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); } else { while (conf) { if (!conf->pskid && accepted_tls == conf->tlsconf && (verifyconfcert(cert, conf, NULL))) { subj = getcertsubject(cert); if (subj) { debug(DBG_WARN, "tlsservernew: TLS connection from %s, client %s, subject %s, %s with cipher %s up", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)), conf->name, subj, SSL_get_version(ssl), SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); free(subj); } X509_free(cert); cert = NULL; break; } conf = find_clconf(handle, (struct sockaddr *)&from, &cur, &hp); } } if (!conf) { debug(DBG_WARN, "tlsservernew: ignoring request, no matching TLS client for %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); goto exit; } client = addclient(conf, 1); if (client) { if (conf->keepalive) enable_keepalive(s); client->ssl = ssl; client->addr = addr_copy((struct sockaddr *)&from); tlsserverrd(client); removeclient(client); } else debug(DBG_WARN, "tlsservernew: failed to create new client instance"); exit: if (cert) X509_free(cert); if (ssl) { SSL_shutdown(ssl); SSL_free(ssl); } shutdown(s, SHUT_RDWR); close(s); pthread_exit(NULL); } void tlsaccept(int s) { int *s_arg; pthread_t tcpserverth; s_arg = malloc(sizeof(s)); if (!s_arg) { debug(DBG_ERR, "tlsaccept: malloc failed"); return; } *s_arg = s; if (pthread_create(&tcpserverth, &pthread_attr, tlsservernew, (void *)s_arg)) { debug(DBG_ERR, "tlsaccept: pthread_create failed"); free(s_arg); shutdown(s, SHUT_RDWR); close(s); return; } pthread_detach(tcpserverth); } void *tlslistener(void *arg) { accepttcp(*(int *)arg, tlsaccept); free(arg); return NULL; } #else const struct protodefs *tlsinit(uint8_t h) { return NULL; } #endif /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/THANKS0000644000076600000240000000125413556476612010552 Thanks to Stefan Winter and Andreas Solberg for talking me into doing this, and the funding from GEANT2. Stefan as well as Kolbjørn Barmen, Ralf Paffrath and Maja Wolniewicz have helped with early testing of the code. Thanks for contributing code goes to Arne Schwabe, Maja Wolniewicz, Simon Leinen and Stefan Winter. All of the above plus Milan Sova have provided good feedback on several implementation choices. Finally thanks to Hans Zandbelt for providing the autoconf stuff. I may have forgotten someone, let me know if you feel left out. For more information, feedback etc. please see the information at http://software.uninett.no/radsecproxy/ Stig Venaas -- 2009.07.22 radsecproxy-1.11.1/raddict.h0000644000076600000240000000157514722543325011420 #ifndef _RADDICT_H #define _RADDICT_H const char *RAD_Attr_Acct_Terminate_Cause_Dict[] = { [1] = "User-Request", "Lost-Carrier", "Lost-Service", "Idle-Timeout", "Session-Timeout", "Admin-Reset", "Admin-Reboot", "Port-Error", "NAS-Error", "NAS-Request", "NAS-Reboot", "Port-Unneeded", "Port-Preempted", "Port-Suspended", "Service-Unavailable", "Callback", "User-Error", "Host-Request", }; const char *RAD_Attr_Acct_Status_Type_Dict[] = { [1] = "Start", [2] = "Stop", [3] = "Interim-Update", [7] = "Accounting-On", [8] = "Accounting-Off", [9] = "Tunnel-Start", [10] = "Tunnel-Stop", [11] = "Tunnel-Reject", [12] = "Tunnel-Link-Start", [13] = "Tunnel-Link-Stop", [14] = "Tunnel-Link-Reject", [15] = "Failed", }; #define RAD_Attr_Dict_Undef "UNKNOWN" #endif /*_RADDICT_H*/ radsecproxy-1.11.1/catgconf.c0000644000076600000240000000367414722543325011567 /* Copyright (c) 2007-2008, UNINETT AS * Copyright (c) 2011-2012, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "debug.h" #include "gconfig.h" #include #include #include #include int listconfig(struct gconffile **cf, char *block, int compact) { char *opt = NULL, *val = NULL; int conftype; for (;;) { free(opt); free(val); if (!getconfigline(cf, block, &opt, &val, &conftype)) return -1; if (!opt) return 0; /* Success. */ if (conftype == CONF_STR && !strcasecmp(opt, "include")) { if (!pushgconfpaths(cf, val)) debugx(1, DBG_ERR, "failed to include config file %s", val); continue; } switch (conftype) { case CONF_STR: if (block) printf(compact ? "%s=%s;" : "\t%s=%s\n", opt, val); else printf("%s=%s\n", opt, val); break; case CONF_CBK: printf("%s %s {%s", opt, val, compact ? "" : "\n"); if (listconfig(cf, val, compact)) return -1; printf("}\n"); break; default: printf("Unsupported config type\n"); return -1; } } return 0; /* Success. */ } int main(int argc, char **argv) { int c, compact = 0; struct gconffile *cfs; debug_init("radsecproxy-conf"); debug_set_level(DBG_WARN); while ((c = getopt(argc, argv, "c")) != -1) { switch (c) { case 'c': compact = 1; break; default: goto usage; } } if (argc - optind != 1) goto usage; cfs = openconfigfile(argv[optind]); return listconfig(&cfs, NULL, compact); usage: debug(DBG_ERR, "Usage:\n%s [ -c ] configfile", argv[0]); exit(1); } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/radsecproxy-hash.8.in0000644000076600000240000000075114452772710013614 .TH radsecproxy-hash 8 "@RELEASEDATE@" "@PACKAGE_STRING@" .SH "NAME" radsecproxy-hash - print digests of Ethernet MAC addresses .SH "SYNOPSIS" .HP 12 radsecproxy-hash [\-h] [\-k \fIKEY\fR] [\fIMAC\fR...] .sp .SH "DESCRIPTION" Print the hash or hmac of Ethernet \fIMAC\fR addresses .SH "OPTIONS" .TP .B \-h Display help and exit .TP .B \-k \fIKEY\fR .br perform HMAC calculation using key \fIKEY\fR .TP With no \fIMAC\fR, read from standard input .SH "SEE ALSO" radsecproxy.conf(5) radsecproxy-1.11.1/radsecproxy-hash.c0000644000076600000240000000330714722543325013260 /* Copyright (c) 2011,2013, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include #include #include #include #include "fticks_hashmac.h" #include "radsecproxy.h" void usage(void) { fprintf(stderr, "usage: radsecproxy-hash [-h] [-k key] [mac]...\n" #if defined(READ_CONFIG) " -c configfile\tuse configuration from CONFIGFILE\n" #endif " -h\t\t\tdisplay this help and exit\n" " -k key\t\tuse KEY for HMAC\n" " mac\t\tMAC address to hash. Read from stdin if omittedn.\n"); exit(1); } #define MYNAME "radsecproxy-hash" void print_hash(uint8_t *mac, uint8_t *key) { uint8_t buf[64 + 1]; if (fticks_hashmac(mac, key, sizeof(buf), buf) != 0) { fprintf(stderr, "%s: out of memory\n", MYNAME); exit(3); } puts((const char *)buf); } int main(int argc, char *argv[]) { int opt; #if defined(READ_CONFIG) char *config = NULL; #endif char mac[80 + 1]; uint8_t *key = NULL; while ((opt = getopt(argc, argv, "hk:")) != -1) { switch (opt) { #if defined(READ_CONFIG) case 'c': config = optarg; break; #endif case 'h': usage(); case 'k': key = (uint8_t *)optarg; break; default: usage(); } } if (optind < argc) { while (optind < argc) { print_hash((uint8_t *)argv[optind++], key); } } else { while (fgets(mac, sizeof(mac), stdin) != NULL) { print_hash((uint8_t *)mac, key); } } return 0; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/radsecproxy.conf-example0000644000076600000240000002233314722543325014473 # Master config file, all possible config options are listed below # First you may define any global options, these are: # # You can optionally specify addresses and ports to listen on # Multiple statements can be used for multiple ports/addresses #ListenUDP *:1814 #ListenUDP localhost #ListenTCP [2001:700:1:7:215:f2ff:fe35:307d]:1812 #ListenTLS 10.10.10.10:2084 #ListenTLS [2001:700:1:7:215:f2ff:fe35:307d]:2084 #ListenDTLS [2001:700:1:7:215:f2ff:fe35:307d]:2084 # To specify a certain address/port for UDP/TLS requests you can use e.g. #SourceUDP 127.0.0.1:33000 #SourceTCP *:33000 #SourceTLS *:33001 #SourceDTLS *:33001 # Optional log level. 3 is default, 1 is less, 5 is more #LogLevel 3 # Optional LogDestination, else stderr used for logging # Logging to file #LogDestination file:///tmp/rp.log # Or logging with Syslog. LOG_DAEMON used if facility not specified # The supported facilities are LOG_DAEMON, LOG_MAIL, LOG_USER and # LOG_LOCAL0, ..., LOG_LOCAL7 #LogDestination x-syslog:/// #LogDestination x-syslog:///log_local2 # Optional log thread Id #LogThreadId on # For generating log entries conforming to the F-Ticks system, specify # FTicksReporting with one of the following values. # None -- Do not log in F-Ticks format. This is the default. # Basic -- Do log in F-Ticks format but do not log VISINST. # Full -- Do log in F-Ticks format and do log VISINST. # Please note that in order to get F-Ticks logging for a given client, # its matching client configuration block has to contain the # fticksVISCOUNTRY option. # You can optionally specify Log MAC and FTicksMAC in order to determine if and # how Calling-Station-Id (users Ethernet MAC address) is being logged. # Static -- Use a static string as a placeholder for # Calling-Station-Id in F-Ticks, of omit it in normal log. # Original -- Log Calling-Station-Id as-is. This is the default for log. # VendorHashed -- Keep first three segments as-is, hash the rest. # VendorKeyHashed -- Like VendorHashed but salt with F-Ticks-Key or Log-key # respectively. This is the default for F-Ticks. # FullyHashed -- Hash the entire string. # FullyKeyHashed -- Like FullyHashed but salt with F-Ticks-Key. # In order to use LogMAC or FTicksMAC with one of VendorKeyHashed or # FullyKeyHashed, specify a key with LogKey or FTicksKey. #LogKey #FTicksKey # Default Log andF-Ticks configuration: #LogMAC Original #FTicksReporting None #FTicksMAC Static # You can optionally specify FTicksSyslogFacility to use a dedicated # syslog facility for F-Ticks messages. This allows for easier filtering # of F-Ticks messages. # F-Ticks messages are always logged using the log level LOG_DEBUG. # Note that specifying a file (using the file:/// prefix) is not supported. #FTicksSyslogFacility log_local1 #FTicksSyslogFacility x-syslog:///log_local1 # If you are using radsecproxy outside the eduroam context, and you want # F-Ticks messages to have your own prefix instead of eduroam, you can set: #FTicksPrefix # There is an option for doing some simple loop prevention. Note that # the LoopPrevention directive can be used in server blocks too, # overriding what's set here in the basic settings. #LoopPrevention on # Add TTL attribute with value 20 if not present (prevents endless loops) #AddTTL 20 # If we have TLS clients or servers we must define at least one tls block. # You can name them whatever you like and then reference them by name when # specifying clients or servers later. There are however three special names # "default", "defaultclient" and "defaultserver". If no name is defined for # a client, the "defaultclient" block will be used if it exists, if not the # "default" will be used. For a server, "defaultserver" followed by "default" # will be checked. # # The simplest configuration you can do is: tls default { # You must specify at least one of CACertificateFile or CACertificatePath # for TLS to work. We always verify peer certificate (client and server) # CACertificateFile /etc/cacerts/CA.pem CACertificatePath /etc/cacerts # You must specify the below for TLS, we always present our certificate CertificateFile /etc/hostcertkey/host.example.com.pem CertificateKeyFile /etc/hostcertkey/host.example.com.key.pem # Optionally specify password if key is encrypted (not very secure) CertificateKeyPassword "follow the white rabbit" # Optionally enable CRL checking # CRLCheck on # Optionally specify how long CAs and CRLs are cached, default forever # CacheExpiry 3600 # Optionally require that peer certs have one of the specified policyOIDs # policyoid 1.2.3 # this option can be used multiple times # policyoid 1.3.4 # Require at least TLS1.2, overriding system defaults # TLSVersion TLS1_2: } # If you want one cert for all clients and another for all servers, use # defaultclient and defaultserver instead of default. If we wanted some # particular server to use something else you could specify a block # "tls myserver" and then reference that for that server. If you always # name the tls block in the client/server config you don't need a default # Now we configure clients, servers and realms. Note that these and # also the lines above may be in any order, except that a realm # can only be configured to use a server that is previously configured. # A realm can be a literal domain name, * which matches all, or a # regexp. A regexp is specified by the character prefix / # For regexp we do case insensitive matching of the entire username string. # The matching of realms is done in the order they are specified, using the # first match found. Some examples are # "@example\.com$", "\.com$", ".*" and "^[a-z].*@example\.com$". # To treat local users separately you might try first specifying "@" # and after that "*". # Configure a rewrite block if you want to add/remove/modify attributes # rewrite example { # # Remove NAS-Port. # removeAttribute 5 # # Remove vendor attribute 100. # removeVendorAttribute 99:100 # # Called-Station-Id = "123456" # addAttribute 30:123456 # # Vendor-99-Attr-101 = 0x0f # addVendorAttribute 99:101:%0f # # Change users @local to @example.com. # modifyAttribute 1:/^(.*)@local$/\1@example.com/ # } client [2001:db8::1] { type tls secret verysecret # we could specify tls here, e.g. # tls myclient # in order to use tls parameters named myclient. We don't, so we will # use "tls defaultclient" if defined, or look for "tls default" as a # last resort } client 127.0.0.1 { type udp secret secret # Might do rewriting of incoming messages using rewrite block example # rewriteIn example # Can also do rewriting of outgoing messages # rewriteOut example } client 127.0.0.1 { type tcp secret secret } client radius.example.com { type tls # secret is optional for TLS } client radius.example.com { type dtls # secret is optional for DTLS } client localhost { type tls pskkey mysecretpresharedkey #a client using TLS-PSK with implicit default psk context and using client name as psk-identity } server 127.0.0.1 { type UDP secret secret # Might do rewriting of incoming messages using rewrite block example # rewriteIn example # Can also do rewriting of outgoing messages # rewriteOut example # Might override loop prevention here too: # LoopPrevention off } realm eduroam.cc { server 127.0.0.1 # If also want to use this server for accounting, specify # accountingServer 127.0.0.1 } server [2001:db8::1] { type TLS port 2283 # secret is optional for TLS # we could specify tls here, e.g. # tls myserver # in order to use tls parameters named myserver. We don't, so we will # use "tls defaultserver" if defined, or look for "tls default" as a # last resort } server radius.example.com { type tls secret radsec StatusServer on # statusserver is optional, can be on or off. Off is default tcpKeepalive on # tcp and tls connections also support TCP keepalives. # Optionally specify the SNI for the outgoing connection # sni www.example.com } #server radius.example.com { # type dtls # secret verysecret # StatusServer on ## statusserver is optional, can be on or off. Off is default #} server radius.example.com { type tls pskidentity my.psk.identity pskkey mysecretpresharedkey #a minimal TLS-PSK server config using implicit default psk context } #server template for dynamic discovery, looking for NAPTR DNS records server dyndisc { type tls tls default dynamicLookupCommand naptr:x-eduroam:radius.tls #alternatively call a script that poerforms the lookup #dynamicLookupCommand /usr/local/bin/naptr-eduroam.sh } # Equivalent to example.com realm /@example\.com$ { server 2001:db8::1 } # One can define a realm without servers, the proxy will then reject # and requests matching this. Optionally one can specify ReplyMessage # attribute to be included in the reject message. One can also use # AccountingResponse option to specify that the proxy should send such. realm /\.com$ { } realm /^anonymous$ { replymessage "No Access" # AccountingResponse On } # The realm below is equivalent to /.* realm * { server dyndisc } # If you don't have a default server you probably want to # reject all unknowns. Optionally you can also include a message #realm * { # replymessage "User unknown" #} radsecproxy-1.11.1/dns.h0000644000076600000240000000306714722543325010570 /* Copyright (c) 2021, SWITCH */ /* See LICENSE for licensing information. */ #ifndef _DNS_H #define _DNS_H #include #include #include /* maximum character string length in a DNS response, including null-terminator */ #define MAXCHARSTRLEN 256 struct naptr_record { uint32_t ttl; uint16_t order; uint16_t preference; char flags[MAXCHARSTRLEN]; char services[MAXCHARSTRLEN]; char regexp[MAXCHARSTRLEN]; char replacement[NS_MAXDNAME]; }; struct srv_record { uint32_t ttl; uint16_t priority; uint16_t weight; uint16_t port; char host[NS_MAXDNAME]; /* TODO add A and AAAA records from additional section */ }; /** * query DNS NAPTR record for name * caller must free memory by calling freenaptrresponse * * @param name the name to query * @param timeout query timeout * @return null terminated array of struct naptr_record* */ struct naptr_record **querynaptr(const char *name, int timeout); /** * free memory allocated by querynaptr * * @param response the response to free */ void freenaptrresponse(struct naptr_record **response); /** * query a DNS SRV record for name. * caller must free memory by calling freesrvresponse. * * @param name the name to query * @param timeout query timeout * @return null terminated array of struct srv_record* */ struct srv_record **querysrv(const char *name, int timeout); /** * free memory allocated by querysrv * * @param response the response to free */ void freesrvresponse(struct srv_record **response); #endif /*_DNS_H*/ radsecproxy-1.11.1/ax_build_date_epoch.m40000644000076600000240000000573714722543325014045 # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_build_date_epoch.html # =========================================================================== # # SYNOPSIS # # AX_BUILD_DATE_EPOCH(VARIABLE[, FORMAT[, ACTION-IF-FAIL]]) # # DESCRIPTION # # Sets VARIABLE to a string representing the current time. It is # formatted according to FORMAT if specified, otherwise it is formatted as # the number of seconds (excluding leap seconds) since the UNIX epoch (01 # Jan 1970 00:00:00 UTC). # # If the SOURCE_DATE_EPOCH environment variable is set, it uses the value # of that variable instead of the current time. See # https://reproducible-builds.org/specs/source-date-epoch). If # SOURCE_DATE_EPOCH is set but cannot be properly interpreted as a UNIX # timestamp, then execute ACTION-IF-FAIL if specified, otherwise error. # # VARIABLE is AC_SUBST-ed. # # LICENSE # # Copyright (c) 2016 Eric Bavier # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_BUILD_DATE_EPOCH], [dnl AC_MSG_CHECKING([for build time]) ax_date_fmt="m4_default($2,%s)" AS_IF([test x"$SOURCE_DATE_EPOCH" = x], [$1=`date "+$ax_date_fmt"`], [ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \ || date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null` AS_IF([test x"$ax_build_date" = x], [m4_ifval([$3], [$3], [AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])], [$1=$ax_build_date])]) AC_MSG_RESULT([$$1]) ])dnl AX_BUILD_DATE_EPOCH radsecproxy-1.11.1/dtls.c0000644000076600000240000005622414722543325010750 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2012,2016-2017, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #define _GNU_SOURCE #include "hash.h" #include "radsecproxy.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RADPROT_DTLS #include "debug.h" #include "hostport.h" #include "util.h" static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(void); void *dtlslistener(void *arg); int dtlsconnect(struct server *server, int timeout, int reconnect); void *dtlsclientrd(void *arg); int clientradputdtls(struct server *server, unsigned char *rad, int radlen); void addserverextradtls(struct clsrvconf *conf); void dtlssetsrcres(void); void initextradtls(void); static const struct protodefs protodefs = { "dtls", "radius/dtls", /* secretdefault */ SOCK_DGRAM, /* socktype */ "2083", /* portdefault */ REQUEST_RETRY_COUNT, /* retrycountdefault */ 10, /* retrycountmax */ REQUEST_RETRY_INTERVAL, /* retryintervaldefault */ 60, /* retryintervalmax */ DUPLICATE_INTERVAL, /* duplicateintervaldefault */ setprotoopts, /* setprotoopts */ getlistenerargs, /* getlistenerargs */ dtlslistener, /* listener */ dtlsconnect, /* connecter */ dtlsclientrd, /* clientconnreader */ clientradputdtls, /* clientradput */ NULL, /* addclient */ NULL, /* addserverextra */ dtlssetsrcres, /* setsrcres */ NULL /* initextra */ }; static struct addrinfo *srcres = NULL; static uint8_t handle; static struct commonprotoopts *protoopts = NULL; const struct protodefs *dtlsinit(uint8_t h) { handle = h; return &protodefs; } static void setprotoopts(struct commonprotoopts *opts) { protoopts = opts; } static char **getlistenerargs(void) { return protoopts ? protoopts->listenargs : NULL; } struct dtlsservernewparams { struct sockaddr_storage addr; struct sockaddr_storage bind; SSL *ssl; }; void dtlssetsrcres(void) { if (!srcres) srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, AF_UNSPEC, NULL, protodefs.socktype); } void *dtlsservernew(void *arg) { struct dtlsservernewparams *params = (struct dtlsservernewparams *)arg; struct client *client; struct clsrvconf *conf; struct list_node *cur = NULL; X509 *cert = NULL; struct tls *accepted_tls = NULL; int s = -1; unsigned long error; struct timeval timeout; struct addrinfo tmpsrvaddr; char tmp[INET6_ADDRSTRLEN], *subj; struct hostportres *hp; debug(DBG_WARN, "dtlsservernew: incoming DTLS connection from %s", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp))); if (!(conf = find_clconf(handle, (struct sockaddr *)¶ms->addr, &cur, &hp))) { debug(DBG_WARN, "dtlsservernew ignoring unknown DTLS client %s", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp))); goto exit; } memset(&tmpsrvaddr, 0, sizeof(struct addrinfo)); tmpsrvaddr.ai_addr = (struct sockaddr *)¶ms->bind; tmpsrvaddr.ai_addrlen = SOCKADDR_SIZE(params->bind); tmpsrvaddr.ai_family = params->bind.ss_family; tmpsrvaddr.ai_socktype = protodefs.socktype; if ((s = bindtoaddr(&tmpsrvaddr, params->addr.ss_family, 1)) < 0) goto exit; if (connect(s, (struct sockaddr *)¶ms->addr, SOCKADDR_SIZE(params->addr))) goto exit; BIO_set_fd(SSL_get_rbio(params->ssl), s, BIO_NOCLOSE); BIO_ctrl(SSL_get_rbio(params->ssl), BIO_CTRL_DGRAM_SET_CONNECTED, 0, (struct sockaddr *)¶ms->addr); if (!SSL_set_ex_data(params->ssl, RSP_EX_DATA_CONFIG_LIST, find_all_clconf(handle, (struct sockaddr *)¶ms->addr, cur, &hp))) { debug(DBG_WARN, "dtlsservernew: failed to set ex data"); } if (sslaccepttimeout(params->ssl, 30) <= 0) { struct clsrvconf *selected = SSL_get_ex_data(params->ssl, RSP_EX_DATA_CONFIG); conf = selected ? selected : conf; while ((error = ERR_get_error())) debug(DBG_ERR, "dtlsservernew: SSL accept from %s (%s) failed: %s", conf->name, addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp)), ERR_error_string(error, NULL)); debug(DBG_ERR, "dtlsservernew: SSL_accept failed"); list_free(SSL_get_ex_data(params->ssl, RSP_EX_DATA_CONFIG_LIST)); goto exit; } list_free(SSL_get_ex_data(params->ssl, RSP_EX_DATA_CONFIG_LIST)); timeout.tv_sec = 5; timeout.tv_usec = 0; if (BIO_ctrl(SSL_get_rbio(params->ssl), BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout) == -1) debug(DBG_WARN, "dtlsservernew: BIO_CTRL_DGRAM_SET_RECV_TIMEOUT failed"); if (!(SSL_session_reused(params->ssl) || (cert = verifytlscert(params->ssl)))) goto exit; { struct clsrvconf *selected = SSL_get_ex_data(params->ssl, RSP_EX_DATA_CONFIG); conf = selected ? selected : conf; } accepted_tls = conf->tlsconf; if (SSL_session_reused(params->ssl)) { debug(DBG_WARN, "dtlsservernew: DTLS connection from %s, client %s, PSK identity %s wtih cipher %s up", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp)), conf->name, conf->pskid, SSL_CIPHER_get_name(SSL_get_current_cipher(params->ssl))); } else { while (conf) { if (!conf->pskid && accepted_tls == conf->tlsconf && (verifyconfcert(cert, conf, NULL))) { subj = getcertsubject(cert); if (subj) { debug(DBG_WARN, "dtlsservernew: DTLS connection from %s, client %s, subject %s, %s with cipher %s up", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp)), conf->name, subj, SSL_get_version(params->ssl), SSL_CIPHER_get_name(SSL_get_current_cipher(params->ssl))); free(subj); } X509_free(cert); cert = NULL; break; } conf = find_clconf(handle, (struct sockaddr *)¶ms->addr, &cur, &hp); } } if (!conf) { debug(DBG_WARN, "dtlsservernew: ignoring request, no matching DTLS client for %s", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp))); goto exit; } client = addclient(conf, 1); if (client) { client->sock = s; client->addr = addr_copy((struct sockaddr *)¶ms->addr); client->ssl = params->ssl; tlsserverrd(client); removeclient(client); } else debug(DBG_WARN, "dtlsservernew: failed to create new client instance"); exit: if (cert) X509_free(cert); if (params->ssl) { SSL_shutdown(params->ssl); SSL_free(params->ssl); } if (s >= 0) close(s); free(params); debug(DBG_DBG, "dtlsservernew: exiting"); pthread_exit(NULL); } int getConnectionInfo(int socket, struct sockaddr *from, socklen_t fromlen, struct sockaddr *to, socklen_t tolen) { uint8_t controlbuf[128]; int ret; struct cmsghdr *ctrlhdr; struct msghdr msghdr; struct in6_pktinfo *info6; struct iovec iov[] = {{.iov_base = NULL, .iov_len = 0}}; char tmp[48]; msghdr.msg_name = from; msghdr.msg_namelen = fromlen; msghdr.msg_iov = iov; msghdr.msg_iovlen = (sizeof(iov) / sizeof(*(iov))); msghdr.msg_control = controlbuf; msghdr.msg_controllen = sizeof(controlbuf); msghdr.msg_flags = 0; if ((ret = recvmsg(socket, &msghdr, MSG_PEEK | MSG_TRUNC)) < 0) { debug(DBG_ERR, "getConnectionInfo: recvmsg failed: %s", strerror(errno)); return ret; } debug(DBG_DBG, "udp packet from: %s", addr2string(from, tmp, sizeof(tmp))); if (getsockname(socket, to, &tolen)) { debug(DBG_ERR, "getConnectionInfo: getsockname failed"); return -1; } for (ctrlhdr = CMSG_FIRSTHDR(&msghdr); ctrlhdr; ctrlhdr = CMSG_NXTHDR(&msghdr, ctrlhdr)) { #if defined(IP_PKTINFO) if (ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_PKTINFO) { struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(ctrlhdr); debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, &(pktinfo->ipi_addr), tmp, sizeof(tmp))); ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; return ret; } #elif defined(IP_RECVDSTADDR) if (ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_RECVDSTADDR) { struct in_addr *addr = (struct in_addr *)CMSG_DATA(ctrlhdr); debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, addr, tmp, sizeof(tmp))); ((struct sockaddr_in *)to)->sin_addr = *addr; return ret; } #endif if (ctrlhdr->cmsg_level == IPPROTO_IPV6 && ctrlhdr->cmsg_type == IPV6_PKTINFO) { info6 = (struct in6_pktinfo *)CMSG_DATA(ctrlhdr); debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET6, &info6->ipi6_addr, tmp, sizeof(tmp))); ((struct sockaddr_in6 *)to)->sin6_addr = info6->ipi6_addr; ((struct sockaddr_in6 *)to)->sin6_scope_id = info6->ipi6_ifindex; return ret; } } debug(DBG_DBG, "getConnecitonInfo: unable to get destination address, using listen info instead"); return ret; } void *dtlslistener(void *arg) { int ndesc, flags, s = *(int *)arg; struct sockaddr_storage from, to; struct dtlsservernewparams *params; struct pollfd fds[1]; pthread_t dtlsserverth; BIO *bio; struct clsrvconf *conf; SSL *ssl; SSL_CTX *ctx; char tmp[INET6_ADDRSTRLEN]; debug(DBG_DBG, "dtlslistener: starting"); if ((flags = fcntl(s, F_GETFL)) == -1) debugx(1, DBG_ERR, "dtlslistener: failed to get socket flags"); if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) debugx(1, DBG_ERR, "dtlslistener: failed to set non-blocking"); for (;;) { fds[0].fd = s; fds[0].events = POLLIN; ndesc = poll(fds, 1, -1); if (ndesc < 0) continue; if (getConnectionInfo(s, (struct sockaddr *)&from, sizeof(from), (struct sockaddr *)&to, sizeof(to)) < 0) { debug(DBG_DBG, "dtlslistener: getConnectionInfo failed"); sock_dgram_skip(s); continue; } conf = find_clconf(handle, (struct sockaddr *)&from, NULL, NULL); if (!conf) { debug(DBG_INFO, "dtlslistener: got UDP from unknown peer %s, ignoring", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); sock_dgram_skip(s); continue; } pthread_mutex_lock(&conf->tlsconf->lock); if (!conf->tlsconf->dtlssslprep) { debug(DBG_DBG, "dtlslistener: no cached ssl object for this context, create new"); ctx = tlsgetctx(handle, conf->tlsconf); if (!ctx) { pthread_mutex_unlock(&conf->tlsconf->lock); continue; } ssl = SSL_new(ctx); if (!ssl) { pthread_mutex_unlock(&conf->tlsconf->lock); debug(DBG_ERR, "dtlslistener: failed to create SSL connection"); continue; } bio = BIO_new_dgram(s, BIO_NOCLOSE); SSL_set_bio(ssl, bio, bio); SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); conf->tlsconf->dtlssslprep = ssl; } else { debug(DBG_DBG, "dtlslistener: reusing cached ssl object"); BIO_set_fd(SSL_get_rbio(conf->tlsconf->dtlssslprep), s, BIO_NOCLOSE); } #if (OPENSSL_VERSION_NUMBER < 0x10100000) || defined(LIBRESSL_VERSION_NUMBER) if (DTLSv1_listen(conf->tlsconf->dtlssslprep, &from) > 0) { #else if (DTLSv1_listen(conf->tlsconf->dtlssslprep, (BIO_ADDR *)&from) > 0) { #endif params = malloc(sizeof(struct dtlsservernewparams)); memcpy(¶ms->addr, &from, sizeof(from)); memcpy(¶ms->bind, &to, sizeof(to)); params->ssl = conf->tlsconf->dtlssslprep; if (!pthread_create(&dtlsserverth, &pthread_attr, dtlsservernew, (void *)params)) { pthread_detach(dtlsserverth); conf->tlsconf->dtlssslprep = NULL; pthread_mutex_unlock(&conf->tlsconf->lock); continue; } else { free(params); } } else { unsigned long error; while ((error = ERR_get_error())) debug(DBG_ERR, "dtlslistener: DTLS_listen failed: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "dtlslistener: DTLS_listen failed or no cookie from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp))); } pthread_mutex_unlock(&conf->tlsconf->lock); } return NULL; } static void cleanup_connection(struct server *server) { if (server->ssl) SSL_shutdown(server->ssl); if (server->sock >= 0) close(server->sock); server->sock = -1; if (server->ssl) SSL_free(server->ssl); server->ssl = NULL; } int dtlsconnect(struct server *server, int timeout, int reconnect) { struct timeval socktimeout, now, start; uint32_t wait; int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; struct hostportres *hp; unsigned long error; BIO *bio; struct addrinfo *source = NULL; char *subj; struct list_node *entry; debug(DBG_DBG, "dtlsconnect: %s to %s", reconnect ? "reconnecting" : "initial connection", server->conf->name); pthread_mutex_lock(&server->lock); if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; pthread_mutex_unlock(&server->lock); if (server->conf->source) { source = resolvepassiveaddrinfo(server->conf->source, AF_UNSPEC, NULL, protodefs.socktype); if (!source) debug(DBG_WARN, "dtlsconnect: could not resolve source address to bind for server %s, using default", server->conf->name); } gettimeofday(&start, NULL); for (;;) { /* ensure previous connection is properly closed */ cleanup_connection(server); wait = connect_wait(start, server->connecttime, firsttry); gettimeofday(&now, NULL); if (timeout && (now.tv_sec - start.tv_sec) + wait > timeout) { debug(DBG_DBG, "dtlsconnect: timeout"); if (source) freeaddrinfo(source); return 0; } if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); sleep(wait); firsttry = 0; for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_INFO, "dtlsconnect: trying to open DTLS connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port); if ((server->sock = bindtoaddr(source ? source : srcres, hp->addrinfo->ai_family, 0)) < 0) { debug(DBG_ERR, "dtlsconnect: failed to bind socket for server %s (%s port %s)", server->conf->name, hp->host, hp->port); goto concleanup; } if (connect(server->sock, hp->addrinfo->ai_addr, hp->addrinfo->ai_addrlen)) { debug(DBG_ERR, "dtlsconnect: failed to connect socket for server %s (%s port %s)", server->conf->name, hp->host, hp->port); goto concleanup; } pthread_mutex_lock(&server->conf->tlsconf->lock); if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))) { pthread_mutex_unlock(&server->conf->tlsconf->lock); debug(DBG_ERR, "dtlsconnect: failed to get TLS context for server %s", server->conf->name); goto concleanup; } server->ssl = SSL_new(ctx); pthread_mutex_unlock(&server->conf->tlsconf->lock); if (!server->ssl) { debug(DBG_ERR, "dtlsconnect: failed to create SSL connection for server %s", server->conf->name); goto concleanup; } if (!SSL_set_ex_data(server->ssl, RSP_EX_DATA_CONFIG, server->conf)) { debug(DBG_WARN, "dtlsconnect: failed to set ex data"); } if (server->conf->sni) { struct in6_addr tmp; char *servername = server->conf->sniservername ? server->conf->sniservername : server->conf->servername ? server->conf->servername : (inet_pton(AF_INET, hp->host, &tmp) || inet_pton(AF_INET6, hp->host, &tmp)) ? NULL : hp->host; if (servername && !tlssetsni(server->ssl, servername)) { debug(DBG_ERR, "dtlsconnect: set SNI %s failed", servername); goto concleanup; } } bio = BIO_new_dgram(server->sock, BIO_CLOSE); BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, hp->addrinfo->ai_addr); if (server->conf->dtlsmtu) { SSL_set_options(server->ssl, SSL_OP_NO_QUERY_MTU); if (!DTLS_set_link_mtu(server->ssl, server->conf->dtlsmtu)) debug(DBG_WARN, "dtlsconnect: failed to set mtu %d", server->conf->dtlsmtu); } SSL_set_bio(server->ssl, bio, bio); if (sslconnecttimeout(server->ssl, 5) <= 0) { while ((error = ERR_get_error())) debug(DBG_ERR, "dtlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL)); debug(DBG_ERR, "dtlsconnect: SSL connect to %s (%s port %s) failed", server->conf->name, hp->host, hp->port); goto concleanup; } socktimeout.tv_sec = 5; socktimeout.tv_usec = 0; if (BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &socktimeout) == -1) debug(DBG_WARN, "dtlsconnect: BIO_CTRL_DGRAM_SET_RECV_TIMEOUT failed"); if (server->conf->pskid && server->conf->pskkey) { if (SSL_session_reused(server->ssl)) { debug(DBG_WARN, "dtlsconnect: DTLS connection to %s (%s port %s), PSK identity %s with cipher %s up", server->conf->name, hp->host, hp->port, server->conf->pskid, SSL_CIPHER_get_name(SSL_get_current_cipher(server->ssl))); break; } else { debug(DBG_ERR, "dtlsconnect: DTLS PSK set for %s (%s port %s) but not used in session, rejecting connection", server->conf->name, hp->host, hp->port); goto concleanup; } } cert = verifytlscert(server->ssl); if (!cert) { debug(DBG_ERR, "dtlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port); goto concleanup; } if (verifyconfcert(cert, server->conf, hp)) { subj = getcertsubject(cert); if (subj) { debug(DBG_WARN, "dtlsconnect: DTLS connection to %s (%s port %s), subject %s up", server->conf->name, hp->host, hp->port, subj); free(subj); } X509_free(cert); break; } else { debug(DBG_ERR, "dtlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port); } X509_free(cert); concleanup: /* ensure previous connection is properly closed */ cleanup_connection(server); } if (server->ssl) break; } gettimeofday(&server->connecttime, NULL); server->tlsnewkey = server->connecttime; pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); server->conreset = reconnect; pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); if (source) freeaddrinfo(source); return 1; } int clientradputdtls(struct server *server, unsigned char *rad, int radlen) { int cnt; struct clsrvconf *conf = server->conf; struct timeval now; if (radlen <= 0) { debug(DBG_ERR, "clientradputdtls: invalid buffer (length)"); return 0; } pthread_mutex_lock(&server->lock); if (server->state != RSP_SERVER_STATE_CONNECTED) { pthread_mutex_unlock(&server->lock); return 0; } gettimeofday(&now, NULL); #if OPENSSL_VERSION_NUMBER >= 0x10101000 if (now.tv_sec - server->tlsnewkey.tv_sec > RSP_TLS_REKEY_INTERVAL && SSL_version(server->ssl) >= TLS1_3_VERSION) { debug(DBG_DBG, "clientradputdtls: perform key update for long-running connection"); if (SSL_get_key_update_type(server->ssl) == SSL_KEY_UPDATE_NONE && !SSL_key_update(server->ssl, SSL_KEY_UPDATE_REQUESTED)) debug(DBG_WARN, "clientradputdtls: request for key update failed for %s", conf->name); server->tlsnewkey = now; } #endif if ((cnt = sslwrite(server->ssl, rad, radlen, 0)) <= 0) { pthread_mutex_unlock(&server->lock); return 0; } debug(DBG_DBG, "clientradputdtls: Sent %d bytes, Radius packet of length %zu to DTLS peer %s", cnt, radlen, conf->name); pthread_mutex_unlock(&server->lock); return 1; } void *dtlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf = NULL; int len = 0; for (;;) { len = radtlsget(server->ssl, server->conf->retryinterval * (server->conf->retrycount + 1), &server->lock, &buf); if (buf && len > 0) { if (!replyh(server, buf, len)) if (closeh(server)) break; buf = NULL; } else if (SSL_get_shutdown(server->ssl)) { if (closeh(server)) break; } else { if (timeouth(server)) break; } } debug(DBG_INFO, "dtlsclientrd: exiting for %s", server->conf->name); pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_FAILING; SSL_shutdown(server->ssl); close(server->sock); /* Wake up clientwr(). */ server->clientrdgone = 1; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); pthread_cond_signal(&server->newrq_cond); pthread_mutex_unlock(&server->newrq_mutex); return NULL; } #else const struct protodefs *dtlsinit(uint8_t h) { return NULL; } #endif /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/tlscommon.h0000644000076600000240000000431314722547134012014 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2016, NORDUnet A/S * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #ifndef _TLSCOMMON_H #define _TLSCOMMON_H #include "hostport.h" #include #if OPENSSL_VERSION_NUMBER < 0x10100000L #define ASN1_STRING_get0_data(o) ((o)->data) #define ASN1_STRING_length(o) ((o)->length) #endif #define RSP_KEYLOG_ENV "SSLKEYLOGFILE" struct tls { char *name; char *cacertfile; char *cacertpath; char *certfile; char *certkeyfile; char *certkeypwd; uint8_t crlcheck; char **policyoids; char *cipherlist; char *ciphersuites; int cacheexpiry; int tlsminversion; int tlsmaxversion; int dtlsminversion; int dtlsmaxversion; #if OPENSSL_VERSION_NUMBER >= 0x30000000 EVP_PKEY *dhparam; #else DH *dhparam; #endif time_t tlsexpiry; time_t dtlsexpiry; X509_VERIFY_PARAM *vpm; SSL_CTX *tlsctx; SSL_CTX *dtlsctx; SSL *dtlssslprep; pthread_mutex_t lock; }; #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) extern int RSP_EX_DATA_CONFIG; extern int RSP_EX_DATA_CONFIG_LIST; void sslinit(void); struct tls *tlsgettls(char *conf); struct tls *tlsgetdefaultpsk(void); SSL_CTX *tlsgetctx(uint8_t type, struct tls *t); X509 *verifytlscert(SSL *ssl); int verifyconfcert(X509 *cert, struct clsrvconf *conf, struct hostportres *); char *getcertsubject(X509 *cert); int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val); int addmatchcertattr(struct clsrvconf *conf, const char *match); void freematchcertattr(struct clsrvconf *conf); void tlsreload(void); int tlssetsni(SSL *ssl, char *sni); int sslconnecttimeout(SSL *ssl, int timeout); int sslaccepttimeout(SSL *ssl, int timeout); int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_mutex_t *lock); int sslwrite(SSL *ssl, void *buf, int num, uint8_t blocking); int radtlsget(SSL *ssl, int timeout, pthread_mutex_t *lock, uint8_t **buf); void tlsserverrd(struct client *client); void terminateinvalidserver(struct server *srv); void terminateinvalidclient(struct client *cli); #endif #endif /*_TLSCOMMON_H*/ /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/Makefile.in0000644000076600000240000012561114724611067011701 # Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ sbin_PROGRAMS = radsecproxy$(EXEEXT) bin_PROGRAMS = radsecproxy-conf$(EXEEXT) radsecproxy-hash$(EXEEXT) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/ax_check_openssl.m4 \ $(top_srcdir)/ax_build_date_epoch.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = radsecproxy.8 radsecproxy-hash.8 \ radsecproxy.conf.5 CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = librsp_a_AR = $(AR) $(ARFLAGS) librsp_a_LIBADD = am_librsp_a_OBJECTS = debug.$(OBJEXT) dns.$(OBJEXT) dtls.$(OBJEXT) \ fticks.$(OBJEXT) fticks_hashmac.$(OBJEXT) gconfig.$(OBJEXT) \ hash.$(OBJEXT) hostport.$(OBJEXT) list.$(OBJEXT) \ radmsg.$(OBJEXT) radsecproxy.$(OBJEXT) rewrite.$(OBJEXT) \ tcp.$(OBJEXT) tls.$(OBJEXT) tlscommon.$(OBJEXT) \ tlv11.$(OBJEXT) udp.$(OBJEXT) util.$(OBJEXT) librsp_a_OBJECTS = $(am_librsp_a_OBJECTS) am_radsecproxy_OBJECTS = main.$(OBJEXT) radsecproxy_OBJECTS = $(am_radsecproxy_OBJECTS) radsecproxy_DEPENDENCIES = librsp.a radsecproxy_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(radsecproxy_LDFLAGS) $(LDFLAGS) -o $@ am_radsecproxy_conf_OBJECTS = catgconf.$(OBJEXT) debug.$(OBJEXT) \ gconfig.$(OBJEXT) util.$(OBJEXT) radsecproxy_conf_OBJECTS = $(am_radsecproxy_conf_OBJECTS) radsecproxy_conf_LDADD = $(LDADD) radsecproxy_conf_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(radsecproxy_conf_LDFLAGS) $(LDFLAGS) -o $@ radsecproxy_hash_SOURCES = radsecproxy-hash.c radsecproxy_hash_OBJECTS = radsecproxy-hash.$(OBJEXT) radsecproxy_hash_DEPENDENCIES = fticks_hashmac.o hash.o list.o AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/catgconf.Po ./$(DEPDIR)/debug.Po \ ./$(DEPDIR)/dns.Po ./$(DEPDIR)/dtls.Po ./$(DEPDIR)/fticks.Po \ ./$(DEPDIR)/fticks_hashmac.Po ./$(DEPDIR)/gconfig.Po \ ./$(DEPDIR)/hash.Po ./$(DEPDIR)/hostport.Po \ ./$(DEPDIR)/list.Po ./$(DEPDIR)/main.Po ./$(DEPDIR)/radmsg.Po \ ./$(DEPDIR)/radsecproxy-hash.Po ./$(DEPDIR)/radsecproxy.Po \ ./$(DEPDIR)/rewrite.Po ./$(DEPDIR)/tcp.Po ./$(DEPDIR)/tls.Po \ ./$(DEPDIR)/tlscommon.Po ./$(DEPDIR)/tlv11.Po \ ./$(DEPDIR)/udp.Po ./$(DEPDIR)/util.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(librsp_a_SOURCES) $(radsecproxy_SOURCES) \ $(radsecproxy_conf_SOURCES) radsecproxy-hash.c DIST_SOURCES = $(librsp_a_SOURCES) $(radsecproxy_SOURCES) \ $(radsecproxy_conf_SOURCES) radsecproxy-hash.c RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(srcdir)/radsecproxy-hash.8.in $(srcdir)/radsecproxy.8.in \ $(srcdir)/radsecproxy.conf.5.in \ $(top_srcdir)/build-aux/compile \ $(top_srcdir)/build-aux/config.guess \ $(top_srcdir)/build-aux/config.sub \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/missing \ $(top_srcdir)/build-aux/tap-driver.sh AUTHORS ChangeLog \ INSTALL NEWS README THANKS build-aux/compile \ build-aux/config.guess build-aux/config.sub build-aux/depcomp \ build-aux/install-sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RELEASEDATE = @RELEASEDATE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ TARGET_CFLAGS = @TARGET_CFLAGS@ TARGET_LDFLAGS = @TARGET_LDFLAGS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign SUBDIRS = tests noinst_LIBRARIES = librsp.a radsecproxy_SOURCES = main.c librsp_a_SOURCES = \ debug.c debug.h \ dns.c dns.h \ dtls.c dtls.h \ fticks.c fticks.h fticks_hashmac.c fticks_hashmac.h \ gconfig.c gconfig.h \ hash.c hash.h \ hostport.c hostport.h \ list.c list.h \ radmsg.c radmsg.h raddict.h \ radsecproxy.c radsecproxy.h \ rewrite.c rewrite.h \ tcp.c tcp.h \ tls.c tls.h \ tlscommon.c tlscommon.h \ tlv11.c tlv11.h \ udp.c udp.h \ util.c util.h radsecproxy_conf_SOURCES = \ catgconf.c \ debug.c debug.h \ gconfig.c gconfig.h \ util.c util.h #################### AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" AM_CFLAGS = \ -g -Wall -Werror -fno-strict-aliasing @OPENSSL_INCLUDES@ @TARGET_CFLAGS@ radsecproxy_LDFLAGS = @OPENSSL_LDFLAGS@ @TARGET_LDFLAGS@ radsecproxy_LDADD = librsp.a @OPENSSL_LIBS@ @LIBS@ radsecproxy_conf_LDFLAGS = @TARGET_LDFLAGS@ radsecproxy_hash_LDADD = fticks_hashmac.o hash.o list.o man_MANS = radsecproxy.8 radsecproxy-hash.8 radsecproxy.conf.5 EXTRA_DIST = \ LICENSE THANKS \ radsecproxy.conf-example \ tools/README tools/naptr-eduroam.sh tools/radsec-dynsrv.sh all: all-recursive .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): radsecproxy.8: $(top_builddir)/config.status $(srcdir)/radsecproxy.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ radsecproxy-hash.8: $(top_builddir)/config.status $(srcdir)/radsecproxy-hash.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ radsecproxy.conf.5: $(top_builddir)/config.status $(srcdir)/radsecproxy.conf.5.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) librsp.a: $(librsp_a_OBJECTS) $(librsp_a_DEPENDENCIES) $(EXTRA_librsp_a_DEPENDENCIES) $(AM_V_at)-rm -f librsp.a $(AM_V_AR)$(librsp_a_AR) librsp.a $(librsp_a_OBJECTS) $(librsp_a_LIBADD) $(AM_V_at)$(RANLIB) librsp.a radsecproxy$(EXEEXT): $(radsecproxy_OBJECTS) $(radsecproxy_DEPENDENCIES) $(EXTRA_radsecproxy_DEPENDENCIES) @rm -f radsecproxy$(EXEEXT) $(AM_V_CCLD)$(radsecproxy_LINK) $(radsecproxy_OBJECTS) $(radsecproxy_LDADD) $(LIBS) radsecproxy-conf$(EXEEXT): $(radsecproxy_conf_OBJECTS) $(radsecproxy_conf_DEPENDENCIES) $(EXTRA_radsecproxy_conf_DEPENDENCIES) @rm -f radsecproxy-conf$(EXEEXT) $(AM_V_CCLD)$(radsecproxy_conf_LINK) $(radsecproxy_conf_OBJECTS) $(radsecproxy_conf_LDADD) $(LIBS) radsecproxy-hash$(EXEEXT): $(radsecproxy_hash_OBJECTS) $(radsecproxy_hash_DEPENDENCIES) $(EXTRA_radsecproxy_hash_DEPENDENCIES) @rm -f radsecproxy-hash$(EXEEXT) $(AM_V_CCLD)$(LINK) $(radsecproxy_hash_OBJECTS) $(radsecproxy_hash_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catgconf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtls.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fticks.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fticks_hashmac.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gconfig.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hostport.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radmsg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radsecproxy-hash.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radsecproxy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rewrite.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tlscommon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tlv11.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(LIBRARIES) $(MANS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f ./$(DEPDIR)/catgconf.Po -rm -f ./$(DEPDIR)/debug.Po -rm -f ./$(DEPDIR)/dns.Po -rm -f ./$(DEPDIR)/dtls.Po -rm -f ./$(DEPDIR)/fticks.Po -rm -f ./$(DEPDIR)/fticks_hashmac.Po -rm -f ./$(DEPDIR)/gconfig.Po -rm -f ./$(DEPDIR)/hash.Po -rm -f ./$(DEPDIR)/hostport.Po -rm -f ./$(DEPDIR)/list.Po -rm -f ./$(DEPDIR)/main.Po -rm -f ./$(DEPDIR)/radmsg.Po -rm -f ./$(DEPDIR)/radsecproxy-hash.Po -rm -f ./$(DEPDIR)/radsecproxy.Po -rm -f ./$(DEPDIR)/rewrite.Po -rm -f ./$(DEPDIR)/tcp.Po -rm -f ./$(DEPDIR)/tls.Po -rm -f ./$(DEPDIR)/tlscommon.Po -rm -f ./$(DEPDIR)/tlv11.Po -rm -f ./$(DEPDIR)/udp.Po -rm -f ./$(DEPDIR)/util.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-local distclean-tags dvi: dvi-recursive dvi-am: html-am: info: info-recursive info-am: install-data-am: install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-sbinPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man5 install-man8 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f ./$(DEPDIR)/catgconf.Po -rm -f ./$(DEPDIR)/debug.Po -rm -f ./$(DEPDIR)/dns.Po -rm -f ./$(DEPDIR)/dtls.Po -rm -f ./$(DEPDIR)/fticks.Po -rm -f ./$(DEPDIR)/fticks_hashmac.Po -rm -f ./$(DEPDIR)/gconfig.Po -rm -f ./$(DEPDIR)/hash.Po -rm -f ./$(DEPDIR)/hostport.Po -rm -f ./$(DEPDIR)/list.Po -rm -f ./$(DEPDIR)/main.Po -rm -f ./$(DEPDIR)/radmsg.Po -rm -f ./$(DEPDIR)/radsecproxy-hash.Po -rm -f ./$(DEPDIR)/radsecproxy.Po -rm -f ./$(DEPDIR)/rewrite.Po -rm -f ./$(DEPDIR)/tcp.Po -rm -f ./$(DEPDIR)/tls.Po -rm -f ./$(DEPDIR)/tlscommon.Po -rm -f ./$(DEPDIR)/tlv11.Po -rm -f ./$(DEPDIR)/udp.Po -rm -f ./$(DEPDIR)/util.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man \ uninstall-sbinPROGRAMS uninstall-man: uninstall-man5 uninstall-man8 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles am--refresh check check-am clean \ clean-binPROGRAMS clean-cscope clean-generic \ clean-noinstLIBRARIES clean-sbinPROGRAMS cscope cscopelist-am \ ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-lzip \ dist-shar dist-tarZ dist-xz dist-zip dist-zstd distcheck \ distclean distclean-compile distclean-generic distclean-local \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man5 install-man8 install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-man uninstall-man5 uninstall-man8 \ uninstall-sbinPROGRAMS .PRECIOUS: Makefile dist-sign: dist distcheck-sign: distcheck dist-sign distcheck-sign: gpg --armor --detach-sign $(DIST_ARCHIVES) distclean-local: rm -f @PACKAGE@-*.tar.gz rm -f @PACKAGE@-*.tar.gz.asc #################### html: radsecproxy.html radsecproxy-hash.html radsecproxy.conf.html %.html: %.8 groff -mandoc -Thtml $< >$@ %.html: %.5 groff -mandoc -Thtml $< >$@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: radsecproxy-1.11.1/gconfig.c0000644000076600000240000003736514722543325011423 /* Copyright (c) 2007-2008, UNINETT AS */ /* See LICENSE for licensing information. */ #include "gconfig.h" #include "debug.h" #include "util.h" #include #include #include #include #include #include #include #include #include /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */ char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) { char *t = s, *q, *r; if (!t || !token || !del) return NULL; while (*t && strchr(del, *t)) t++; if (!*t || (comment && strchr(comment, *t))) { *token = NULL; return t + 1; /* needs to be non-NULL, but value doesn't matter */ } if (quote && (q = strchr(quote, *t))) { t++; r = t; while (*t && *t != *q) t++; if (!*t || (t[1] && !strchr(del, t[1]))) return NULL; *t = '\0'; *token = r; return t + 1; } *token = t; t++; while (*t && !strchr(del, *t)) t++; *t = '\0'; return t + 1; } int pushgconfdata(struct gconffile **cf, const char *data) { int i; struct gconffile *newcf; if (!*cf) { newcf = malloc(sizeof(struct gconffile) * 2); if (!newcf) return 0; memset(newcf, 0, sizeof(struct gconffile) * 2); } else { for (i = 0; (*cf)[i].data || (*cf)[i].path;) i++; newcf = realloc(*cf, sizeof(struct gconffile) * (i + 2)); if (!newcf) return 0; memmove(newcf + 1, newcf, sizeof(struct gconffile) * (i + 1)); memset(newcf, 0, sizeof(struct gconffile)); } newcf[0].data = data; *cf = newcf; return 1; } FILE *pushgconffile(struct gconffile **cf, FILE *file, const char *description) { int i; struct gconffile *newcf; char *desc; if (!file) { debug(DBG_INFO, "could not read config from %s", description); return NULL; } debug(DBG_DBG, "reading config from %s", description); desc = stringcopy(description, 0); if (!desc) goto errmalloc; if (!*cf) { newcf = malloc(sizeof(struct gconffile) * 2); if (!newcf) goto errmalloc; memset(newcf, 0, sizeof(struct gconffile) * 2); } else { for (i = 0; (*cf)[i].data || (*cf)[i].path;) i++; newcf = realloc(*cf, sizeof(struct gconffile) * (i + 2)); if (!newcf) goto errmalloc; memmove(newcf + 1, newcf, sizeof(struct gconffile) * (i + 1)); memset(newcf, 0, sizeof(struct gconffile)); } newcf[0].file = file; newcf[0].path = desc; *cf = newcf; return file; errmalloc: free(desc); fclose(file); debug(DBG_ERR, "malloc failed"); return NULL; } FILE *pushgconfpath(struct gconffile **cf, const char *path) { FILE *f; f = fopen(path, "r"); return pushgconffile(cf, f, path); } FILE *pushgconfpaths(struct gconffile **cf, const char *cfgpath) { int i; FILE *f = NULL; glob_t globbuf; char *path, *curfile = NULL, *dir; /* if cfgpath is relative, make it relative to current config */ if (*cfgpath == '/') path = (char *)cfgpath; else { /* dirname may modify its argument */ curfile = stringcopy((*cf)->path, 0); if (!curfile) { debug(DBG_ERR, "malloc failed"); goto exit; } dir = dirname(curfile); path = malloc(strlen(dir) + strlen(cfgpath) + 2); if (!path) { debug(DBG_ERR, "malloc failed"); goto exit; } strcpy(path, dir); path[strlen(dir)] = '/'; strcpy(path + strlen(dir) + 1, cfgpath); } memset(&globbuf, 0, sizeof(glob_t)); if (glob(path, 0, NULL, &globbuf)) { debug(DBG_WARN, "could not glob %s", path); goto exit; } for (i = globbuf.gl_pathc - 1; i >= 0; i--) { f = pushgconfpath(cf, globbuf.gl_pathv[i]); if (!f) break; } globfree(&globbuf); exit: if (curfile) { free(curfile); free(path); } return f; } int popgconf(struct gconffile **cf) { int i; if (!*cf) return 0; for (i = 0; (*cf)[i].data || (*cf)[i].path;) i++; if (i && (*cf)[0].file) { fclose((*cf)[0].file); if ((*cf)[0].path) { debug(DBG_DBG, "closing config file %s", (*cf)[0].path); free((*cf)[0].path); } } if (i < 2) { free(*cf); *cf = NULL; return 0; } memmove(*cf, *cf + 1, sizeof(struct gconffile) * i); return 1; } void freegconfmstr(char **mstr) { int i; if (mstr) { for (i = 0; mstr[i]; i++) free(mstr[i]); free(mstr); } } void freegconf(struct gconffile **cf) { int i; if (!*cf) return; for (i = 0; (*cf)[i].data || (*cf)[i].path; i++) { if ((*cf)[i].file) { fclose((*cf)[i].file); if ((*cf)[i].path) { debug(DBG_DBG, "closing config file %s", (*cf)[i].path); free((*cf)[i].path); } } } free(*cf); *cf = NULL; } struct gconffile *openconfigfile(const char *file) { struct gconffile *cf = NULL; if (!pushgconfpath(&cf, file)) { debug(DBG_ERR, "could not read config file %s\n%s", file, strerror(errno)); return NULL; } debug(DBG_DBG, "reading config file %s", file); return cf; } /* Parses config with following syntax: * One of these: * option-name value * option-name = value * Or: * option-name value { * option-name [=] value * ... * } */ int getlinefromcf(struct gconffile *cf, char *line, const size_t size) { size_t i, pos; if (!cf) return 0; if (cf->file) return fgets(line, size, cf->file) ? 1 : 0; else if (cf->data) { pos = cf->datapos; if (!cf->data[pos]) return 0; for (i = pos; cf->data[i] && cf->data[i] != '\n';) i++; if (cf->data[i] == '\n') i++; if (i - pos > size - 1) i = size - 1 + pos; memcpy(line, cf->data + pos, i - pos); line[i - pos] = '\0'; cf->datapos = i; return 1; } return 0; } int getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype) { char line[2048]; char *tokens[3], *s; int tcount; *opt = NULL; *val = NULL; *conftype = 0; if (!cf || !*cf || (!(*cf)->file && !(*cf)->data)) return 1; for (;;) { if (!getlinefromcf(*cf, line, 2048)) { if (popgconf(cf)) continue; return 1; } s = line; for (tcount = 0; tcount < 3; tcount++) { s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#"); if (!s) { debug(DBG_ERR, "Syntax error in line starting with: %s", line); return 0; } if (!tokens[tcount]) break; } if (!tcount || **tokens == '#') continue; if (**tokens == '}') { if (block) return 1; debug(DBG_ERR, "configuration error, found } with no matching {"); return 0; } break; } switch (tcount) { case 2: *opt = stringcopy(tokens[0], 0); if (!*opt) goto errmalloc; *val = stringcopy(tokens[1], 0); if (!*val) goto errmalloc; *conftype = CONF_STR; break; case 3: if (tokens[1][0] == '=' && tokens[1][1] == '\0') { *opt = stringcopy(tokens[0], 0); if (!*opt) goto errmalloc; *val = stringcopy(tokens[2], 0); if (!*val) goto errmalloc; *conftype = CONF_STR; break; } if (tokens[2][0] == '{' && tokens[2][1] == '\0') { *opt = stringcopy(tokens[0], 0); if (!*opt) goto errmalloc; *val = stringcopy(tokens[1], 0); if (!*val) goto errmalloc; *conftype = CONF_CBK; break; } /* fall through */ default: if (block) debug(DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]); else debug(DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]); return 0; } if (**val) return 1; debug(DBG_ERR, "configuration error, option %s needs a non-empty value", *opt); goto errexit; errmalloc: debug(DBG_ERR, "malloc failed"); errexit: free(*opt); *opt = NULL; free(*val); *val = NULL; return 0; } static uint8_t hexdigit2int(char d) { if (d >= '0' && d <= '9') return d - '0'; if (d >= 'a' && d <= 'f') return 10 + d - 'a'; if (d >= 'A' && d <= 'F') return 10 + d - 'A'; return 0; } static int ishexbyte(char *str, uint8_t accept_null) { if (str[0] && str[1]) return (isxdigit((int)str[0]) && isxdigit((int)str[1]) && (accept_null || !(str[0] == '0' && str[1] == '0'))); return 0; } static char hextochar(char *hex) { return 16 * hexdigit2int(hex[0]) + hexdigit2int(hex[1]); } int unhex(char *str, uint8_t process_null) { char *t = str, *s = str; while (*t) { if (t[0] == '%' && ishexbyte(t + 1, process_null)) { *s++ = hextochar(t + 1); t += 3; } else if (t[0] == '%' && t[1] == '%') { t += 2; while (ishexbyte(t, process_null)) { *s++ = hextochar(t); t += 2; } } else *s++ = *t++; } *s = '\0'; return (s - str); } typedef int (*t_fptr)(struct gconffile **, void *, char *, char *, char *); /* returns 1 if ok, 0 on error */ /* caller must free returned values also on error */ int getgenericconfig(struct gconffile **cf, char *block, ...) { va_list ap; char *opt = NULL, *val, *word, *optval, **str = NULL, ***mstr = NULL, **newmstr, *endptr; uint8_t *bln = NULL; long int *lint = NULL; int type = 0, conftype = 0, n; t_fptr cbk = NULL; void *cbkarg = NULL; for (;;) { free(opt); if (!getconfigline(cf, block, &opt, &val, &conftype)) return 0; if (!opt) return 1; if (conftype == CONF_STR && !strcasecmp(opt, "include")) { if (!pushgconfpaths(cf, val)) { debug(DBG_ERR, "failed to include config file %s", val); goto errexit; } free(val); continue; } va_start(ap, block); while ((word = va_arg(ap, char *))) { type = va_arg(ap, int); switch (type) { case CONF_STR: /*intentional fall-thru, these are identical*/ case CONF_STR_NOESC: str = va_arg(ap, char **); if (!str) goto errparam; break; case CONF_MSTR: /*intentional fall-thru, these are identical*/ case CONF_MSTR_NOESC: mstr = va_arg(ap, char ***); if (!mstr) goto errparam; break; case CONF_BLN: bln = va_arg(ap, uint8_t *); if (!bln) goto errparam; break; case CONF_LINT: lint = va_arg(ap, long int *); if (!lint) goto errparam; break; case CONF_CBK: cbk = va_arg(ap, t_fptr); if (!cbk) goto errparam; cbkarg = va_arg(ap, void *); break; default: goto errparam; } if (!strcasecmp(opt, word)) break; } va_end(ap); if (!word) { if (block) debug(DBG_ERR, "configuration error in block %s, unknown option %s", block, opt); debug(DBG_ERR, "configuration error, unknown option %s", opt); goto errexit; } if (((type == CONF_STR || type == CONF_STR_NOESC || type == CONF_MSTR || type == CONF_MSTR_NOESC || type == CONF_BLN || type == CONF_LINT) && conftype != CONF_STR) || (type == CONF_CBK && conftype != CONF_CBK)) { if (block) debug(DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt); debug(DBG_ERR, "configuration error, wrong syntax for option %s", opt); goto errexit; } switch (type) { case CONF_STR: /*intentional fall-thru, these are almost identical*/ case CONF_STR_NOESC: if (*str) { debug(DBG_ERR, "configuration error, option %s already set to %s", opt, *str); goto errexit; } if (type == CONF_STR) unhex(val, 0); *str = val; break; case CONF_MSTR: /*intentional fall-thru, these are almost identical*/ case CONF_MSTR_NOESC: if (*mstr) for (n = 0; (*mstr)[n];) n++; else n = 0; newmstr = realloc(*mstr, sizeof(char *) * (n + 2)); if (!newmstr) { debug(DBG_ERR, "malloc failed"); goto errexit; } if (type == CONF_MSTR) unhex(val, 0); newmstr[n] = val; newmstr[n + 1] = NULL; *mstr = newmstr; break; case CONF_BLN: if (!strcasecmp(val, "on")) *bln = 1; else if (!strcasecmp(val, "off")) *bln = 0; else { if (block) debug(DBG_ERR, "configuration error in block %s, value for option %s must be on or off, not %s", block, opt, val); else debug(DBG_ERR, "configuration error, value for option %s must be on or off, not %s", opt, val); goto errexit; } break; case CONF_LINT: endptr = NULL; *lint = strtol(val, &endptr, 0); if (*lint == LONG_MIN || *lint == LONG_MAX || !endptr || endptr == val || *endptr != '\0') { if (block) debug(DBG_ERR, "configuration error in block %s, value for option %s must be an integer, not %s", block, opt, val); else debug(DBG_ERR, "configuration error, value for option %s must be an integer, not %s", opt, val); goto errexit; } break; case CONF_CBK: optval = malloc(strlen(opt) + strlen(val) + 2); if (!optval) { debug(DBG_ERR, "malloc failed"); goto errexit; } sprintf(optval, "%s %s", opt, val); if (!cbk(cf, cbkarg, optval, opt, val)) { free(optval); goto errexit; } free(val); free(optval); continue; default: goto errparam; } if (block) debug(DBG_DBG, "getgenericconfig: block %s: %s = %s", block, opt, val); else debug(DBG_DBG, "getgenericconfig: %s = %s", opt, val); if (type == CONF_BLN || type == CONF_LINT) free(val); } errparam: debug(DBG_ERR, "getgenericconfig: internal parameter error"); errexit: va_end(ap); free(opt); free(val); return 0; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/aclocal.m40000644000076600000240000012254514724611066011476 # generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],, [m4_warning([this file was generated for autoconf 2.72. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) radsecproxy-1.11.1/tlv11.h0000644000076600000240000000125714722543325010752 /* Copyright (c) 2008, UNINETT AS * Copyright (c) 2010, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include struct tlv { uint8_t t; uint8_t l; uint8_t *v; }; struct tlv *maketlv(uint8_t, uint8_t, void *); struct tlv *copytlv(struct tlv *); void freetlv(struct tlv *); int eqtlv(struct tlv *, struct tlv *); struct list *copytlvlist(struct list *); void freetlvlist(struct list *); void rmtlv(struct list *, uint8_t); uint8_t *tlv2str(struct tlv *tlv); struct tlv *resizetlv(struct tlv *, uint8_t); uint32_t tlv2longint(struct tlv *tlv); char *tlv2ipv4addr(struct tlv *tlv); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/hash.h0000644000076600000240000000215614722543325010725 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ #include #include struct hash { struct list *hashlist; pthread_mutex_t mutex; }; struct hash_entry { void *key; uint32_t keylen; void *data; struct list_node *next; /* used when walking through hash */ }; /* allocates and initialises hash structure; returns NULL if malloc fails */ struct hash *hash_create(void); /* frees all memory associated with the hash */ void hash_destroy(struct hash *hash); /* insert entry in hash; returns 1 if ok, 0 if malloc fails */ int hash_insert(struct hash *hash, void *key, uint32_t keylen, void *data); /* reads entry from hash */ void *hash_read(struct hash *hash, void *key, uint32_t keylen); /* extracts (read and remove) entry from hash */ void *hash_extract(struct hash *hash, void *key, uint32_t keylen); /* returns first entry */ struct hash_entry *hash_first(struct hash *hash); /* returns the next entry after the argument */ struct hash_entry *hash_next(struct hash_entry *entry); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/radmsg.c0000644000076600000240000003503314722543325011252 /* Copyright (c) 2007-2009, UNINETT AS * Copyright (c) 2023, SWITCH */ /* See LICENSE for licensing information. */ #include "debug.h" #include "list.h" #include "raddict.h" #include "radmsg.h" #include "util.h" #include #include #include #include #include #include /* radius message length is a 16bit value starting at byte 2, in network order*/ #define RADLEN(buf) ntohs(*(uint16_t *)(buf + 2)) /** * @brief Get the length of a radius message form its raw buffer. * Note the buffer must contain at least the first 4 bytes. * * @param buf raw message buffer * @return int the length of the radius message if valid, or its negative value if invalid. * A 0 value is also consiedered invalid. */ int get_checked_rad_length(uint8_t *buf) { int len = RADLEN(buf); if (len < RAD_Min_Length || len > RAD_Max_Length) { return -len; } return len; } void radmsg_free(struct radmsg *msg) { if (msg) { freetlvlist(msg->attrs); memset(msg, 0, sizeof(struct radmsg)); free(msg); } } struct radmsg *radmsg_init(uint8_t code, uint8_t id, uint8_t *auth) { struct radmsg *msg; msg = malloc(sizeof(struct radmsg)); if (!msg) return NULL; memset(msg, 0, sizeof(struct radmsg)); msg->attrs = list_create(); if (!msg->attrs) { free(msg); return NULL; } msg->code = code; msg->id = id; if (auth) memcpy(msg->auth, auth, 16); else if (!RAND_bytes(msg->auth, 16)) { free(msg); return NULL; } return msg; } int radmsg_add(struct radmsg *msg, struct tlv *attr, uint8_t front) { if (!msg || !msg->attrs) return 1; if (!attr || attr->l > RAD_Max_Attr_Value_Length) return 0; return front ? list_push_front(msg->attrs, attr) : list_push(msg->attrs, attr); } /** Return a new list with all tlv's in \a msg of type \a type. The * caller is responsible for freeing the list by calling \a * list_free(). */ struct list *radmsg_getalltype(const struct radmsg *msg, uint8_t type) { struct list *list = NULL; struct list_node *node = NULL; if (!msg || !msg->attrs) return NULL; list = list_create(); if (!list) return NULL; for (node = list_first(msg->attrs); node; node = list_next(node)) if (((struct tlv *)node->data)->t == type) if (list_push(list, node->data) != 1) { list_free(list); return NULL; } return list; } /* returns first tlv of the given type */ struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) { struct list_node *node; struct tlv *tlv; if (!msg) return NULL; for (node = list_first(msg->attrs); node; node = list_next(node)) { tlv = (struct tlv *)node->data; if (tlv->t == type) return tlv; } return NULL; } /** Copy all attributes of type \a type from \a src to \a dst. * * If all attributes were copied successfully, the number of * attributes copied is returned. * * If copying failed, a negative number is returned. */ int radmsg_copy_attrs(struct radmsg *dst, const struct radmsg *src, uint8_t type) { struct list_node *node = NULL; struct list *list = radmsg_getalltype(src, type); int n = 0; for (node = list_first(list); node; node = list_next(node)) { if (radmsg_add(dst, copytlv((struct tlv *)node->data), 0) != 1) { n = -1; break; } n++; } list_free(list); return n; } int _checkmsgauth(unsigned char *rad, int radlen, uint8_t *authattr, uint8_t *secret, int secret_len) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct hmac_md5_ctx hmacctx; uint8_t auth[MD5_DIGEST_SIZE], hash[MD5_DIGEST_SIZE]; pthread_mutex_lock(&lock); /* hmac is calculated with message-authenticator being sixteen octets of zero */ memcpy(auth, authattr, sizeof(auth)); memset(authattr, 0, MD5_DIGEST_SIZE); hmac_md5_set_key(&hmacctx, secret_len, secret); hmac_md5_update(&hmacctx, radlen, rad); hmac_md5_digest(&hmacctx, sizeof(hash), hash); memcpy(authattr, auth, MD5_DIGEST_SIZE); pthread_mutex_unlock(&lock); return (memcmp(auth, hash, MD5_DIGEST_SIZE) == 0); } int _validauth(unsigned char *rad, int len, unsigned char *reqauth, unsigned char *sec, int sec_len) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct md5_ctx mdctx; unsigned char hash[MD5_DIGEST_SIZE]; int result = 0; /* Fail. */ pthread_mutex_lock(&lock); md5_init(&mdctx); md5_update(&mdctx, 4, rad); md5_update(&mdctx, 16, reqauth); if (len > 20) md5_update(&mdctx, len - 20, rad + 20); md5_update(&mdctx, sec_len, sec); md5_digest(&mdctx, sizeof(hash), hash); result = !memcmp(hash, rad + 4, 16); pthread_mutex_unlock(&lock); return result; } int _createmessageauth(unsigned char *rad, int radlen, unsigned char *authattrval, uint8_t *secret, int secret_len) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct hmac_md5_ctx hmacctx; if (!authattrval) return 1; pthread_mutex_lock(&lock); memset(authattrval, 0, 16); hmac_md5_set_key(&hmacctx, secret_len, secret); hmac_md5_update(&hmacctx, radlen, rad); hmac_md5_digest(&hmacctx, MD5_DIGEST_SIZE, authattrval); pthread_mutex_unlock(&lock); return 1; } int _radsign(unsigned char *rad, int radlen, unsigned char *sec, int sec_len) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct md5_ctx mdctx; pthread_mutex_lock(&lock); md5_init(&mdctx); md5_update(&mdctx, radlen, rad); md5_update(&mdctx, sec_len, sec); md5_digest(&mdctx, MD5_DIGEST_SIZE, rad + 4); pthread_mutex_unlock(&lock); return 1; } uint8_t *tlv2buf(uint8_t *p, const struct tlv *tlv) { p[0] = tlv->t; p[1] = tlv->l + 2; if (tlv->l) { if (tlv->v) memcpy(p + 2, tlv->v, tlv->l); else memset(p + 2, 0, tlv->l); } return p; } int radmsg2buf(struct radmsg *msg, uint8_t *secret, int secret_len, uint8_t **buf) { struct list_node *node; struct tlv *tlv; int size; uint8_t *p, *msgauth = NULL; if (!msg || !msg->attrs) return -1; size = 20; for (node = list_first(msg->attrs); node; node = list_next(node)) size += 2 + ((struct tlv *)node->data)->l; if (size > 65535) return -1; *buf = malloc(size); if (!*buf) return -1; p = *buf; *p++ = msg->code; *p++ = msg->id; *(uint16_t *)p = htons(size); p += 2; memcpy(p, msg->auth, 16); p += 16; for (node = list_first(msg->attrs); node; node = list_next(node)) { tlv = (struct tlv *)node->data; p = tlv2buf(p, tlv); if (tlv->t == RAD_Attr_Message_Authenticator && secret) msgauth = ATTRVAL(p); p += tlv->l + 2; } if (msgauth && !_createmessageauth(*buf, size, msgauth, secret, secret_len)) { free(*buf); *buf = NULL; return -1; } if (secret) { if ((msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Access_Challenge || msg->code == RAD_Accounting_Response || msg->code == RAD_Accounting_Request) && !_radsign(*buf, size, secret, secret_len)) { free(*buf); *buf = NULL; return -1; } if (msg->code == RAD_Accounting_Request) memcpy(msg->auth, *buf + 4, 16); } return size; } /* if secret set we also validate message authenticator if present */ struct radmsg *buf2radmsg(uint8_t *buf, int len, uint8_t *secret, int secret_len, uint8_t *rqauth) { struct radmsg *msg; uint8_t t, l, *v = NULL, *p, auth[16]; struct tlv *attr; if (len != RADLEN(buf)) { debug(DBG_WARN, "buf2radmsg: length field does not match buffer length, ignoring message"); return NULL; } if (secret && buf[0] == RAD_Accounting_Request) { memset(auth, 0, 16); if (!_validauth(buf, len, auth, secret, secret_len)) { debug(DBG_WARN, "buf2radmsg: Accounting-Request message authentication failed"); return NULL; } } if (rqauth && secret && !_validauth(buf, len, rqauth, secret, secret_len)) { debug(DBG_WARN, "buf2radmsg: Invalid auth, ignoring reply"); return NULL; } msg = radmsg_init(buf[0], buf[1], (uint8_t *)buf + 4); if (!msg) return NULL; p = buf + 20; while (p - buf + 2 <= len) { t = *p++; l = *p++; if (l < 2 || l > 255) { debug(DBG_WARN, "buf2radmsg: invalid attribute length %d", l); radmsg_free(msg); return NULL; } l -= 2; if (l) { if (p - buf + l > len) { debug(DBG_WARN, "buf2radmsg: attribute length %d exceeds packet length", l + 2); radmsg_free(msg); return NULL; } v = p; p += l; } if (t == RAD_Attr_Message_Authenticator && secret) { if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Access_Challenge) { if (rqauth) memcpy(buf + 4, rqauth, 16); else { debug(DBG_DBG, "buf2radmsg: unable to verify message authenticator, missing original access-request"); msg->msgauthinvalid = 1; } } else if (msg->code != RAD_Access_Request) debug(DBG_DBG, "buf2radmsg: unexpeted message-authnticator"); if (l != 16 || !_checkmsgauth(buf, len, v, secret, secret_len)) { debug(DBG_DBG, "buf2radmsg: message authenticator invalid"); msg->msgauthinvalid = 1; } else debug(DBG_DBG, "buf2radmsg: message authenticator ok"); if (rqauth) memcpy(buf + 4, msg->auth, 16); } attr = maketlv(t, l, v); if (!attr || !radmsg_add(msg, attr, 0)) { freetlv(attr); radmsg_free(msg); return NULL; } } if (p - buf < len) { debug(DBG_WARN, "buf2radmsg: attributes did not fill packet"); radmsg_free(msg); return NULL; } return msg; } /* should accept both names and numeric values, only numeric right now */ uint8_t attrname2val(char *attrname) { int val = 0; val = atoi(attrname); return val > 0 && val < 256 ? val : 0; } /* ATTRNAME is on the form vendor[:type]. If only vendor is found, TYPE is set to 256 and 1 is returned. If type is >= 256, 1 is returned. Otherwise, 0 is returned. */ /* should accept both names and numeric values, only numeric right now */ int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) { char *s; *vendor = atoi(attrname); s = strchr(attrname, ':'); if (!s) { /* Only vendor was found. */ *type = 256; return 1; } *type = atoi(s + 1); return *type < 256; } int attrvalidate(unsigned char *attrs, int length) { while (length > 1) { if (ATTRLEN(attrs) < 2) { debug(DBG_INFO, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs)); return 0; } length -= ATTRLEN(attrs); if (length < 0) { debug(DBG_INFO, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs)); return 0; } attrs += ATTRLEN(attrs); } if (length) debug(DBG_INFO, "attrvalidate: malformed packet? remaining byte after last attribute"); return 1; } /** Create vendor specific tlv with ATTR. ATTR is consumed (freed) if * all is well with the new tlv, i.e. if the function returns * !NULL. */ struct tlv *makevendortlv(uint32_t vendor, struct tlv *attr) { struct tlv *newtlv = NULL; uint8_t l, *v; if (!attr || attr->l > (RAD_Max_Attr_Value_Length - 6)) return NULL; l = attr->l + 2 + 4; v = malloc(l); if (v) { vendor = htonl(vendor & 0x00ffffff); /* MSB=0 according to RFC 2865. */ memcpy(v, &vendor, 4); tlv2buf(v + 4, attr); newtlv = maketlv(RAD_Attr_Vendor_Specific, l, v); free(v); if (newtlv) freetlv(attr); } return newtlv; } int resizeattr(struct tlv *attr, uint8_t newlen) { if (newlen > RAD_Max_Attr_Value_Length) return 0; if (resizetlv(attr, newlen)) return 1; return 0; } /** * @brief verify eap message attributes for correct format (length) * * @param msg the messageto verify * @return int 1 if correct (or no eap attributes), 0 if format error */ int verifyeapformat(struct radmsg *msg) { struct list *eap_attrs; struct list_node *node; size_t eap_len = 0, attr_len = 0; int ret = 1; if (!(eap_attrs = radmsg_getalltype(msg, RAD_Attr_EAP_Message))) return 1; if (!(node = list_first(eap_attrs))) { ret = 1; goto exit; } if (((struct tlv *)node->data)->l < 4) { debug(DBG_DBG, "verifyeapformat: first eap attribute too short"); ret = 0; goto exit; } eap_len = ntohs(*(uint16_t *)(((struct tlv *)node->data)->v + 2)); for (; node; node = list_next(node)) { struct tlv *attr = (struct tlv *)node->data; if (attr->l == 0) { debug(DBG_DBG, "verifyeapformat: empty eap attribute"); ret = 0; goto exit; } attr_len += attr->l; } if (eap_len != attr_len) { debug(DBG_DBG, "verifyeapformat: eap length (%d) does not match attribute content length (%d)", eap_len, attr_len); ret = 0; goto exit; } exit: list_free(eap_attrs); return ret; } const char *attrval2strdict(struct tlv *attr) { uint32_t val; if (!attr) return NULL; val = tlv2longint(attr); switch (attr->t) { case RAD_Attr_Acct_Status_Type: if (val < sizeof(RAD_Attr_Acct_Status_Type_Dict) / sizeof(RAD_Attr_Acct_Status_Type_Dict[0])) return RAD_Attr_Acct_Status_Type_Dict[val] ? RAD_Attr_Acct_Status_Type_Dict[val] : RAD_Attr_Dict_Undef; break; case RAD_Attr_Acct_Terminate_Cause: if (val < sizeof(RAD_Attr_Acct_Terminate_Cause_Dict) / sizeof(RAD_Attr_Acct_Terminate_Cause_Dict[0])) return RAD_Attr_Acct_Terminate_Cause_Dict[val] ? RAD_Attr_Acct_Terminate_Cause_Dict[val] : RAD_Attr_Dict_Undef; break; default: break; } return NULL; } /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/udp.h0000644000076600000240000000030313320713715010555 /* Copyright (c) 2008, UNINETT AS */ /* See LICENSE for licensing information. */ const struct protodefs *udpinit(uint8_t h); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ radsecproxy-1.11.1/fticks.h0000644000076600000240000000101014722543325011251 /* Copyright (c) 2011, NORDUnet A/S */ /* See LICENSE for licensing information. */ #include "radsecproxy.h" int fticks_configure(struct options *options, uint8_t **reportingp, uint8_t **macp, uint8_t **keyp); void fticks_log(const struct options *options, const struct client *client, const struct radmsg *msg, const struct request *rq); /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */