diff --git a/configure.ac b/configure.ac index 3a9e67ec..3c25707e 100644 --- a/configure.ac +++ b/configure.ac @@ -256,7 +256,8 @@ AC_CHECK_MEMBER([struct sockaddr.sa_len], AC_CHECK_HEADERS([net/if_tun.h linux/if_tun.h netinet/in_systm.h], [], [], []) -AC_CHECK_FUNCS([setproctitle vasprintf clock_gettime isatty pselect getpeereid sigaltstack posix_memalign malloc_trim]) +AC_CHECK_FUNCS([setproctitle vasprintf clock_gettime isatty pselect getpeereid sigaltstack]) +AC_CHECK_FUNCS([strlcpy posix_memalign malloc_trim]) if [ test -z "$LIBWRAP" ];then libwrap_enabled="no" diff --git a/src/common.c b/src/common.c index e8213b1c..6a318f52 100644 --- a/src/common.c +++ b/src/common.c @@ -419,3 +419,57 @@ void *_talloc_size2(void *ctx, size_t size) { return talloc_size(ctx, size); } + +#ifndef HAVE_STRLCPY + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Copyright 2006 The FreeRADIUS server project + */ + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +oc_strlcpy(char *dst, char const *src, size_t siz) +{ + char *d = dst; + char const *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif + diff --git a/src/common.h b/src/common.h index d941a4eb..e49e4b7f 100644 --- a/src/common.h +++ b/src/common.h @@ -114,4 +114,9 @@ void ms_sleep(unsigned ms) nanosleep(&tv, NULL); } +#ifndef HAVE_STRLCPY +size_t oc_strlcpy(char *dst, char const *src, size_t siz); +# define strlcpy oc_strlcpy +#endif + #endif diff --git a/src/config.c b/src/config.c index 7bad1b33..28444e77 100644 --- a/src/config.c +++ b/src/config.c @@ -233,7 +233,7 @@ unsigned j; #define READ_STATIC_STRING(name, s_name) { \ val = get_option(name, &mand); \ if (val != NULL && val->valType == OPARG_TYPE_STRING) \ - snprintf(s_name, sizeof(s_name), "%s", val->v.strVal); \ + strlcpy(s_name, val->v.strVal, sizeof(s_name)); \ else if (mand != 0) { \ fprintf(stderr, "Configuration option %s is mandatory.\n", name); \ exit(1); \ @@ -796,7 +796,7 @@ int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config) (*config)->foreground = 1; if (HAVE_OPT(PID_FILE)) { - snprintf(pid_file, sizeof(pid_file), "%s", OPT_ARG(PID_FILE)); + strlcpy(pid_file, OPT_ARG(PID_FILE), sizeof(pid_file)); } if (HAVE_OPT(DEBUG)) diff --git a/src/main-auth.c b/src/main-auth.c index 5520101a..6e677a9b 100644 --- a/src/main-auth.c +++ b/src/main-auth.c @@ -183,7 +183,7 @@ struct cookie_entry_st *old; if (cmsg->username == NULL) return -1; - snprintf(proc->username, sizeof(proc->username), "%s", cmsg->username); + strlcpy(proc->username, cmsg->username, sizeof(proc->username)); if (cmsg->sid.len != sizeof(proc->sid)) return -1; @@ -201,7 +201,7 @@ struct cookie_entry_st *old; /* override the group name in order to load the correct configuration in * case his group is specified in the certificate */ if (cmsg->groupname) - snprintf(proc->groupname, sizeof(proc->groupname), "%s", cmsg->groupname); + strlcpy(proc->groupname, cmsg->groupname, sizeof(proc->groupname)); /* cookie is good so far, now read config (in order to know * whether roaming is allowed or not */ @@ -277,7 +277,7 @@ struct cookie_entry_st *old; } if (cmsg->hostname) - snprintf(proc->hostname, sizeof(proc->hostname), "%s", cmsg->hostname); + strlcpy(proc->hostname, cmsg->hostname, sizeof(proc->hostname)); memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed)); diff --git a/src/main-ctl-unix.c b/src/main-ctl-unix.c index dcd8570a..288a62f3 100644 --- a/src/main-ctl-unix.c +++ b/src/main-ctl-unix.c @@ -108,7 +108,7 @@ int ctl_handler_init(main_server_st * s) mslog(s, NULL, LOG_DEBUG, "initializing control unix socket: %s", s->config->occtl_socket_file); memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; - snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", s->config->occtl_socket_file); + strlcpy(sa.sun_path, s->config->occtl_socket_file, sizeof(sa.sun_path)); remove(s->config->occtl_socket_file); sd = socket(AF_UNIX, SOCK_STREAM, 0); diff --git a/src/main-misc.c b/src/main-misc.c index f88ff02d..d73cc880 100644 --- a/src/main-misc.c +++ b/src/main-misc.c @@ -74,7 +74,7 @@ int set_tun_mtu(main_server_st * s, struct proc_st *proc, unsigned mtu) return -1; memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name); + strlcpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_mtu = mtu; ret = ioctl(fd, SIOCSIFMTU, &ifr); @@ -580,17 +580,14 @@ int handle_commands(main_server_st * s, struct proc_st *proc) } if (tmsg->tls_ciphersuite) - snprintf(proc->tls_ciphersuite, - sizeof(proc->tls_ciphersuite), "%s", - tmsg->tls_ciphersuite); + strlcpy(proc->tls_ciphersuite, tmsg->tls_ciphersuite, + sizeof(proc->tls_ciphersuite)); if (tmsg->dtls_ciphersuite) - snprintf(proc->dtls_ciphersuite, - sizeof(proc->dtls_ciphersuite), "%s", - tmsg->dtls_ciphersuite); + strlcpy(proc->dtls_ciphersuite, tmsg->dtls_ciphersuite, + sizeof(proc->dtls_ciphersuite)); if (tmsg->user_agent) - snprintf(proc->user_agent, - sizeof(proc->user_agent), "%s", - tmsg->user_agent); + strlcpy(proc->user_agent, tmsg->user_agent, + sizeof(proc->user_agent)); session_info_msg__free_unpacked(tmsg, &pa); } @@ -759,8 +756,7 @@ void run_sec_mod(main_server_st * s) snprintf(s->full_socket_file, sizeof(s->full_socket_file), "%s/%s", s->config->chroot_dir, s->socket_file); } else { - snprintf(s->full_socket_file, sizeof(s->full_socket_file), "%s", - s->socket_file); + strlcpy(s->full_socket_file, s->socket_file, sizeof(s->full_socket_file)); } p = s->full_socket_file; @@ -800,7 +796,7 @@ void put_into_cgroup(main_server_st * s, const char *_cgroup, pid_t pid) #ifdef __linux__ /* format: cpu,memory:cgroup-name */ - snprintf(cgroup, sizeof(cgroup), "%s", _cgroup); + strlcpy(cgroup, _cgroup, sizeof(cgroup)); name = strchr(cgroup, ':'); if (name == NULL) { diff --git a/src/main-user.c b/src/main-user.c index a997eeae..0b05047e 100644 --- a/src/main-user.c +++ b/src/main-user.c @@ -169,8 +169,8 @@ add_utmp_entry(main_server_st *s, struct proc_st* proc) memset(&entry, 0, sizeof(entry)); entry.ut_type = USER_PROCESS; entry.ut_pid = proc->pid; - snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->tun_lease.name); - snprintf(entry.ut_user, sizeof(entry.ut_user), "%s", proc->username); + strlcpy(entry.ut_line, proc->tun_lease.name, sizeof(entry.ut_line)); + strlcpy(entry.ut_user, proc->username, sizeof(entry.ut_user)); #ifdef __linux__ if (proc->remote_addr_len == sizeof(struct sockaddr_in)) memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr), sizeof(struct in_addr)); @@ -207,7 +207,7 @@ static void remove_utmp_entry(main_server_st *s, struct proc_st* proc) memset(&entry, 0, sizeof(entry)); entry.ut_type = DEAD_PROCESS; if (proc->tun_lease.name[0] != 0) - snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->tun_lease.name); + strlcpy(entry.ut_line, proc->tun_lease.name, sizeof(entry.ut_line)); entry.ut_pid = proc->pid; setutxent(); diff --git a/src/main.c b/src/main.c index 893c5e21..427f5f09 100644 --- a/src/main.c +++ b/src/main.c @@ -201,7 +201,7 @@ int _listen_unix_ports(void *pool, struct cfg_st* config, if (config->unix_conn_file) { memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; - snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", config->unix_conn_file); + strlcpy(sa.sun_path, config->unix_conn_file, sizeof(sa.sun_path)); remove(sa.sun_path); if (config->foreground != 0) @@ -1004,7 +1004,7 @@ int main(int argc, char** argv) tls_load_certs(s, &creds); s->secmod_addr.sun_family = AF_UNIX; - snprintf(s->secmod_addr.sun_path, sizeof(s->secmod_addr.sun_path), "%s", s->socket_file); + strlcpy(s->secmod_addr.sun_path, s->socket_file, sizeof(s->secmod_addr.sun_path)); s->secmod_addr_len = SUN_LEN(&s->secmod_addr); /* initialize memory for worker process */ diff --git a/src/sec-mod-auth.c b/src/sec-mod-auth.c index 4421fd2f..d203a273 100644 --- a/src/sec-mod-auth.c +++ b/src/sec-mod-auth.c @@ -221,11 +221,9 @@ static int check_user_group_status(sec_mod_st * sec, client_entry_st * e, return -1; } - snprintf(e->username, sizeof(e->username), "%s", - cert_user); + strlcpy(e->username, cert_user, sizeof(e->username)); if (cert_groups_size > 0 && sec->config->cert_group_oid != NULL && e->groupname[0] == 0) - snprintf(e->groupname, sizeof(e->groupname), - "%s", cert_groups[0]); + strlcpy(e->groupname, cert_groups[0], sizeof(e->groupname)); } else { if (sec->config->cert_user_oid != NULL && cert_user && strcmp(e->username, cert_user) != 0) { seclog(sec, LOG_INFO, @@ -482,7 +480,7 @@ int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req) } if (req->hostname != NULL) { - snprintf(e->hostname, sizeof(e->hostname), "%s", req->hostname); + strlcpy(e->hostname, req->hostname, sizeof(e->hostname)); } if (sec->config->auth_types & AUTH_TYPE_USERNAME_PASS) { @@ -506,8 +504,7 @@ int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req) module->auth_user(e->auth_ctx, e->username, sizeof(e->username)); if (ret != 0 && req->user_name != NULL) { - snprintf(e->username, sizeof(e->username), "%s", - req->user_name); + strlcpy(e->username, req->user_name, sizeof(e->username)); } } @@ -517,7 +514,7 @@ int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req) for (i=0;in_cert_group_names;i++) { if (strcmp(req->group_name, req->cert_group_names[i]) == 0) { - snprintf(e->groupname, sizeof(e->groupname), "%s", req->cert_group_names[i]); + strlcpy(e->groupname, req->cert_group_names[i], sizeof(e->groupname)); found = 1; break; } diff --git a/src/sec-mod-ban.c b/src/sec-mod-ban.c index e789170b..8a8f1cc8 100644 --- a/src/sec-mod-ban.c +++ b/src/sec-mod-ban.c @@ -99,7 +99,7 @@ void add_ip_to_ban_list(sec_mod_st *sec, const char *ip, time_t reenable_time) return; } - snprintf(e->ip, sizeof(e->ip), "%s", ip); + strlcpy(e->ip, ip, sizeof(e->ip)); e->expires = reenable_time; if (htable_add(db, rehash(e, NULL), e) == 0) { @@ -138,7 +138,7 @@ unsigned check_if_banned(sec_mod_st *sec, const char *ip) /* pass the current time somehow */ t.expires = time(0); - snprintf(t.ip, sizeof(t.ip), "%s", ip); + strlcpy(t.ip, ip, sizeof(t.ip)); if (htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t) != 0) return 1; diff --git a/src/sec-mod-db.c b/src/sec-mod-db.c index e5044464..50caa776 100644 --- a/src/sec-mod-db.c +++ b/src/sec-mod-db.c @@ -94,7 +94,7 @@ client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip) return NULL; } - snprintf(e->ip, sizeof(e->ip), "%s", ip); + strlcpy(e->ip, ip, sizeof(e->ip)); ret = gnutls_rnd(GNUTLS_RND_RANDOM, e->sid, sizeof(e->sid)); if (ret < 0) { seclog(sec, LOG_ERR, "error generating SID"); diff --git a/src/sec-mod.c b/src/sec-mod.c index da4e1559..e1daf1bc 100644 --- a/src/sec-mod.c +++ b/src/sec-mod.c @@ -488,7 +488,7 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; - snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file); + strlcpy(sa.sun_path, socket_file, sizeof(sa.sun_path)); remove(socket_file); #define SOCKET_FILE sa.sun_path diff --git a/src/tlslib.c b/src/tlslib.c index 5afed144..db79f6c8 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -644,7 +644,7 @@ struct key_cb_data * cdata; memset(&cdata->sa, 0, sizeof(cdata->sa)); cdata->sa.sun_family = AF_UNIX; - snprintf(cdata->sa.sun_path, sizeof(cdata->sa.sun_path), "%s", s->socket_file); + strlcpy(cdata->sa.sun_path, s->socket_file, sizeof(cdata->sa.sun_path)); cdata->sa_len = SUN_LEN(&cdata->sa); /* load the private key */ diff --git a/src/tun.c b/src/tun.c index 5172972d..66eac588 100644 --- a/src/tun.c +++ b/src/tun.c @@ -77,7 +77,7 @@ int set_ipv6_addr(main_server_st * s, struct proc_st *proc) } memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); ret = ioctl(fd, SIOGIFINDEX, &ifr); if (ret != 0) { @@ -108,7 +108,7 @@ int set_ipv6_addr(main_server_st * s, struct proc_st *proc) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET6; ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); ret = ioctl(fd, SIOCSIFFLAGS, &ifr); if (ret != 0) { @@ -146,7 +146,7 @@ int set_ipv6_addr(main_server_st * s, struct proc_st *proc) } memset(&ifr6, 0, sizeof(ifr6)); - snprintf(ifr6.ifra_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr6.ifra_name, proc->tun_lease.name, IFNAMSIZ); memcpy(&ifr6.ifra_addr.sin6_addr, SA_IN6_P(&proc->ipv6->lip), SA_IN_SIZE(proc->ipv6->lip_len)); @@ -177,7 +177,7 @@ int set_ipv6_addr(main_server_st * s, struct proc_st *proc) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET6; ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, oroc->tun_lease.name, IFNAMSIZ); ret = ioctl(fd, SIOCSIFFLAGS, &ifr); if (ret != 0) { @@ -221,7 +221,7 @@ static int set_network_info(main_server_st * s, struct proc_st *proc) return -1; #ifdef SIOCAIFADDR - snprintf(ifr.ifra_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifra_name, proc->tun_lease.name, IFNAMSIZ); memcpy(&ifr.ifra_addr, &proc->ipv4->lip, proc->ipv4->lip_len); ifr.ifra_addr.sin_len = sizeof(struct sockaddr_in); @@ -244,7 +244,7 @@ static int set_network_info(main_server_st * s, struct proc_st *proc) goto cleanup; } #else - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); memcpy(&ifr.ifr_addr, &proc->ipv4->lip, proc->ipv4->lip_len); ifr.ifr_addr.sa_family = AF_INET; @@ -259,7 +259,7 @@ static int set_network_info(main_server_st * s, struct proc_st *proc) memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); memcpy(&ifr.ifr_dstaddr, &proc->ipv4->rip, proc->ipv4->rip_len); ifr.ifr_dstaddr.sa_family = AF_INET; @@ -277,7 +277,7 @@ static int set_network_info(main_server_st * s, struct proc_st *proc) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); ret = ioctl(fd, SIOCSIFFLAGS, &ifr); if (ret != 0) { @@ -410,8 +410,7 @@ int open_tun(main_server_st * s, struct proc_st *proc) goto fail; } - snprintf(proc->tun_lease.name, sizeof(proc->tun_lease.name), - "%s", devname(st.st_rdev, S_IFCHR)); + strlcpy(proc->tun_lease.name, devname(st.st_rdev, S_IFCHR), sizeof(proc->tun_lease.name)); } set_cloexec_flag(tunfd, 1); @@ -455,7 +454,7 @@ void close_tun(main_server_st * s, struct proc_st *proc) return -1; memset(&ifr, 0, sizeof(struct ifreq)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", proc->tun_lease.name); + strlcpy(ifr.ifr_name, proc->tun_lease.name, IFNAMSIZ); ret = ioctl(fd, SIOCIFDESTROY, &ifr); if (ret != 0) { diff --git a/src/worker-auth.c b/src/worker-auth.c index d644b61e..e8d01d22 100644 --- a/src/worker-auth.c +++ b/src/worker-auth.c @@ -490,14 +490,11 @@ static int recv_cookie_auth_reply(worker_st * ws) goto cleanup; } - snprintf(ws->vinfo.name, sizeof(ws->vinfo.name), "%s", - msg->vname); - snprintf(ws->username, sizeof(ws->username), "%s", - msg->user_name); + strlcpy(ws->vinfo.name, msg->vname, sizeof(ws->vinfo.name)); + strlcpy(ws->username, msg->user_name, sizeof(ws->username)); if (msg->group_name != NULL) { - snprintf(ws->groupname, sizeof(ws->groupname), "%s", - msg->group_name); + strlcpy(ws->groupname, msg->group_name, sizeof(ws->groupname)); } else { ws->groupname[0] = 0; } @@ -691,7 +688,7 @@ static int recv_auth_reply(worker_st * ws, int sd, char *txt, return ERR_AUTH_FAIL; } - snprintf(txt, max_txt_size, "%s", msg->msg); + strlcpy(txt, msg->msg, max_txt_size); if (msg->has_sid && msg->sid.len == sizeof(ws->sid)) { /* update our sid */ memcpy(ws->sid, msg->sid.data, sizeof(ws->sid)); @@ -706,8 +703,7 @@ static int recv_auth_reply(worker_st * ws, int sd, char *txt, goto cleanup; } - snprintf(ws->username, sizeof(ws->username), "%s", - msg->user_name); + strlcpy(ws->username, msg->user_name, sizeof(ws->username)); if (msg->has_sid && msg->sid.len == sizeof(ws->sid)) { /* update our sid */ @@ -1087,8 +1083,7 @@ int post_auth_handler(worker_st * ws, unsigned http_ver) strcmp(groupname, ws->config->default_select_group) == 0) { def_group = 1; } else { - snprintf(ws->groupname, sizeof(ws->groupname), "%s", - groupname); + strlcpy(ws->groupname, groupname, sizeof(ws->groupname)); ireq.group_name = ws->groupname; } } @@ -1105,8 +1100,7 @@ int post_auth_handler(worker_st * ws, unsigned http_ver) goto ask_auth; } - snprintf(ws->username, sizeof(ws->username), "%s", - username); + strlcpy(ws->username, username, sizeof(ws->username)); talloc_free(username); ireq.user_name = ws->username; }