mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Fix subtle errors in kpasswd
This commit is contained in:
@@ -28,26 +28,54 @@
|
|||||||
#define TMP_TEMPLATE "/tmp/kpasswd.XXXXXX"
|
#define TMP_TEMPLATE "/tmp/kpasswd.XXXXXX"
|
||||||
#define KPASSWD_PORT 464
|
#define KPASSWD_PORT 464
|
||||||
|
|
||||||
|
/* blacklist entries are released only BLCAKLIST_TIMEOUT seconds
|
||||||
|
* after the children performing the noperation has finished.
|
||||||
|
* this is to avoid races */
|
||||||
|
|
||||||
|
#define BLACKLIST_TIMEOUT 5
|
||||||
|
|
||||||
struct blacklist {
|
struct blacklist {
|
||||||
struct blacklist *next;
|
struct blacklist *next;
|
||||||
char *address;
|
char *address;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
time_t expire;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct blacklist *global_blacklist = NULL;
|
static struct blacklist *global_blacklist = NULL;
|
||||||
|
|
||||||
int check_blacklist(char *address)
|
int check_blacklist(char *address)
|
||||||
{
|
{
|
||||||
struct blacklist *bl;
|
struct blacklist *bl, *prev_bl;
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
if (!global_blacklist) {
|
if (!global_blacklist) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bl = global_blacklist; bl; bl = bl->next) {
|
prev_bl = NULL;
|
||||||
|
bl = global_blacklist;
|
||||||
|
while (bl) {
|
||||||
|
if (bl->expire && (bl->expire < now)) {
|
||||||
|
if (prev_bl) {
|
||||||
|
prev_bl->next = bl->next;
|
||||||
|
free(bl->address);
|
||||||
|
free(bl);
|
||||||
|
bl = prev_bl->next;
|
||||||
|
} else {
|
||||||
|
global_blacklist = bl->next;
|
||||||
|
free(bl->address);
|
||||||
|
free(bl);
|
||||||
|
bl = global_blacklist;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(address, bl->address) == 0) {
|
if (strcmp(address, bl->address) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_bl = bl;
|
||||||
|
bl = bl->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -62,6 +90,7 @@ int add_blacklist(pid_t pid, char *address)
|
|||||||
|
|
||||||
bl->next = NULL;
|
bl->next = NULL;
|
||||||
bl->pid = pid;
|
bl->pid = pid;
|
||||||
|
bl->expire = 0;
|
||||||
bl->address = strdup(address);
|
bl->address = strdup(address);
|
||||||
if (!bl->address) {
|
if (!bl->address) {
|
||||||
free(bl);
|
free(bl);
|
||||||
@@ -83,26 +112,18 @@ int add_blacklist(pid_t pid, char *address)
|
|||||||
|
|
||||||
int remove_blacklist(pid_t pid)
|
int remove_blacklist(pid_t pid)
|
||||||
{
|
{
|
||||||
struct blacklist *bl, *pbl;
|
struct blacklist *bl;
|
||||||
|
|
||||||
if (!global_blacklist) {
|
if (!global_blacklist) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pbl = NULL;
|
|
||||||
bl = global_blacklist;
|
bl = global_blacklist;
|
||||||
while (bl) {
|
while (bl) {
|
||||||
if (pid == bl->pid) {
|
if (pid == bl->pid) {
|
||||||
if (pbl == NULL) {
|
bl->expire = time(NULL) + BLACKLIST_TIMEOUT;
|
||||||
global_blacklist = bl->next;
|
|
||||||
} else {
|
|
||||||
pbl->next = bl->next;
|
|
||||||
}
|
|
||||||
free(bl->address);
|
|
||||||
free(bl);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pbl = bl;
|
|
||||||
bl = bl->next;
|
bl = bl->next;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -944,6 +965,7 @@ pid_t handle_conn(int fd, int type)
|
|||||||
{
|
{
|
||||||
int mfd, tcp;
|
int mfd, tcp;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
char addrto6[INET6_ADDRSTRLEN+1];
|
||||||
char address[INET6_ADDRSTRLEN+1];
|
char address[INET6_ADDRSTRLEN+1];
|
||||||
uint8_t request[1500];
|
uint8_t request[1500];
|
||||||
ssize_t reqlen;
|
ssize_t reqlen;
|
||||||
@@ -966,17 +988,38 @@ pid_t handle_conn(int fd, int type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mfd = fd;
|
/* read first to empty the buffer on udp connections */
|
||||||
|
reqlen = recvfrom(fd, request, sizeof(request), 0,
|
||||||
|
(struct sockaddr *)&from, &fromlen);
|
||||||
|
if (reqlen <= 0) {
|
||||||
|
syslog(LOG_ERR, "Error receiving request (%d) %s",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) getnameinfo((struct sockaddr *)&from, fromlen,
|
(void) getnameinfo((struct sockaddr *)&from, fromlen,
|
||||||
address, INET6_ADDRSTRLEN+1,
|
addrto6, INET6_ADDRSTRLEN+1,
|
||||||
NULL, 0, NI_NUMERICHOST);
|
NULL, 0, NI_NUMERICHOST);
|
||||||
|
|
||||||
if (debug > 0) {
|
if (debug > 0) {
|
||||||
syslog(LOG_ERR, "Connection from %s", address);
|
syslog(LOG_ERR, "Connection from %s", addrto6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strchr(addrto6, ':') == NULL) {
|
||||||
|
char *prefix6 = "::ffff:";
|
||||||
|
/* this is an IPv4 formatted addr
|
||||||
|
* convert to IPv6 mapped addr */
|
||||||
|
memcpy(address, prefix6, 7);
|
||||||
|
memcpy(&address[7], addrto6, INET6_ADDRSTRLEN-7);
|
||||||
|
} else {
|
||||||
|
/* regular IPv6 address, copy as is */
|
||||||
|
memcpy(address, addrto6, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
/* make sure we have termination */
|
||||||
|
address[INET6_ADDRSTRLEN] = '\0';
|
||||||
|
|
||||||
/* Check blacklist for requests from the same IP until operations
|
/* Check blacklist for requests from the same IP until operations
|
||||||
* are finished on the active client.
|
* are finished on the active client.
|
||||||
* the password change may be slow and pam_krb5 sends up to 3 UDP
|
* the password change may be slow and pam_krb5 sends up to 3 UDP
|
||||||
@@ -991,15 +1034,17 @@ pid_t handle_conn(int fd, int type)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reqlen = recvfrom(mfd, request, sizeof(request), 0,
|
/* now read data if it was a TCP connection */
|
||||||
(struct sockaddr *)&from, &fromlen);
|
if (tcp) {
|
||||||
if (reqlen <= 0) {
|
reqlen = recvfrom(mfd, request, sizeof(request), 0,
|
||||||
syslog(LOG_ERR, "Error receiving request (%d) %s",
|
(struct sockaddr *)&from, &fromlen);
|
||||||
errno, strerror(errno));
|
if (reqlen <= 0) {
|
||||||
if (tcp) close(mfd);
|
syslog(LOG_ERR, "Error receiving request (%d) %s",
|
||||||
return -1;
|
errno, strerror(errno));
|
||||||
|
close(mfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* handle kerberos and ldap operations in childrens */
|
/* handle kerberos and ldap operations in childrens */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@@ -1017,6 +1062,7 @@ pid_t handle_conn(int fd, int type)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* children */
|
/* children */
|
||||||
|
if (debug > 0) syslog(LOG_ERR, "Servicing %s", address);
|
||||||
|
|
||||||
/* TCP packets prepend the lenght as a 32bit network order field,
|
/* TCP packets prepend the lenght as a 32bit network order field,
|
||||||
* this information seem to be just redundant, so let's simply
|
* this information seem to be just redundant, so let's simply
|
||||||
@@ -1031,13 +1077,13 @@ pid_t handle_conn(int fd, int type)
|
|||||||
if (tcp) {
|
if (tcp) {
|
||||||
sendret = sendto(mfd, reply, replen, 0, NULL, 0);
|
sendret = sendto(mfd, reply, replen, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
sendret = sendto(mfd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
|
sendret = sendto(fd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
|
||||||
}
|
}
|
||||||
if (sendret == -1) {
|
if (sendret == -1) {
|
||||||
syslog(LOG_ERR, "Error sending reply (%d)", errno);
|
syslog(LOG_ERR, "Error sending reply (%d)", errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(mfd);
|
if (tcp) close(mfd);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,6 +1235,8 @@ int main(int argc, char *argv[])
|
|||||||
/* check for children exiting */
|
/* check for children exiting */
|
||||||
cid = waitpid(-1, &cstatus, WNOHANG);
|
cid = waitpid(-1, &cstatus, WNOHANG);
|
||||||
if (cid != -1 && cid != 0) {
|
if (cid != -1 && cid != 0) {
|
||||||
|
if (debug > 0)
|
||||||
|
syslog(LOG_ERR, "pid %d completed operations!\n", cid);
|
||||||
remove_blacklist(cid);
|
remove_blacklist(cid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user