summaryrefslogtreecommitdiffstats
path: root/ipa-server/ipa-kpasswd
diff options
context:
space:
mode:
Diffstat (limited to 'ipa-server/ipa-kpasswd')
-rw-r--r--ipa-server/ipa-kpasswd/ipa_kpasswd.c349
1 files changed, 280 insertions, 69 deletions
diff --git a/ipa-server/ipa-kpasswd/ipa_kpasswd.c b/ipa-server/ipa-kpasswd/ipa_kpasswd.c
index f5540b74c..b0020c04f 100644
--- a/ipa-server/ipa-kpasswd/ipa_kpasswd.c
+++ b/ipa-server/ipa-kpasswd/ipa_kpasswd.c
@@ -28,26 +28,54 @@
#define TMP_TEMPLATE "/tmp/kpasswd.XXXXXX"
#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 *next;
char *address;
pid_t pid;
+ time_t expire;
};
static struct blacklist *global_blacklist = NULL;
int check_blacklist(char *address)
{
- struct blacklist *bl;
+ struct blacklist *bl, *prev_bl;
+ time_t now = time(NULL);
if (!global_blacklist) {
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) {
return 1;
}
+
+ prev_bl = bl;
+ bl = bl->next;
}
return 0;
@@ -62,6 +90,7 @@ int add_blacklist(pid_t pid, char *address)
bl->next = NULL;
bl->pid = pid;
+ bl->expire = 0;
bl->address = strdup(address);
if (!bl->address) {
free(bl);
@@ -83,32 +112,24 @@ int add_blacklist(pid_t pid, char *address)
int remove_blacklist(pid_t pid)
{
- struct blacklist *bl, *pbl;
+ struct blacklist *bl;
if (!global_blacklist) {
return -1;
}
- pbl = NULL;
bl = global_blacklist;
while (bl) {
if (pid == bl->pid) {
- if (pbl == NULL) {
- global_blacklist = bl->next;
- } else {
- pbl->next = bl->next;
- }
- free(bl->address);
- free(bl);
+ bl->expire = time(NULL) + BLACKLIST_TIMEOUT;
return 0;
}
- pbl = bl;
bl = bl->next;
}
return -1;
}
-int debug = 1;
+int debug = 0;
char *srv_pri_name = "kadmin/changepw";
char *keytab_name = NULL;
@@ -255,12 +276,19 @@ int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
return ret;
}
-int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd)
+/* from DS ldaprot.h */
+#define LDAP_TAG_PWP_WARNING 0xA0 /* context specific + constructed + 0 */
+#define LDAP_TAG_PWP_SECSLEFT 0x80L /* context specific + primitive */
+#define LDAP_TAG_PWP_GRCLOGINS 0x81L /* context specific + primitive + 1 */
+#define LDAP_TAG_PWP_ERROR 0x81L /* context specific + primitive + 1 */
+
+int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd, char **errstr)
{
char *tmp_file = NULL;
int version;
LDAP *ld = NULL;
BerElement *ctrl = NULL;
+ BerElement *sctrl = NULL;
struct berval control;
struct berval newpw;
char hostname[1024];
@@ -275,7 +303,12 @@ int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd)
struct berval *retdata = NULL;
struct timeval tv;
LDAPMessage *entry, *res = NULL;
- int ret;
+ LDAPControl **srvctrl = NULL;
+ char *exterr1 = NULL;
+ char *exterr2 = NULL;
+ char *err;
+ int msgid;
+ int ret, rc;
tmp_file = strdup(TMP_TEMPLATE);
if (!tmp_file) {
@@ -399,7 +432,12 @@ int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd)
if (ret != LDAP_SUCCESS) {
syslog(LOG_ERR, "Search for %s failed with error %d",
filter, ret);
- ret = KRB5_KPASSWD_HARDERROR;
+ if (ret == LDAP_CONSTRAINT_VIOLATION) {
+ *errstr = strdup("Password Change Failed");
+ ret = KRB5_KPASSWD_SOFTERROR;
+ } else {
+ ret = KRB5_KPASSWD_HARDERROR;
+ }
goto done;
}
free(filter);
@@ -409,6 +447,7 @@ int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd)
userdn = ldap_get_dn(ld, entry);
ldap_msgfree(res);
+ res = NULL;
if (!userdn) {
syslog(LOG_ERR, "No userdn, can't change password!");
@@ -430,25 +469,164 @@ int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd)
ret = ber_flatten2(ctrl, &control, 0);
if (ret < 0) {
syslog(LOG_ERR, "ber flattening failed!");
- ret = -1;
+ ret = KRB5_KPASSWD_HARDERROR;
goto done;
}
/* perform password change */
- ret = ldap_extended_operation_s(ld, LDAP_EXOP_MODIFY_PASSWD, &control,
- NULL, NULL, &retoid, &retdata);
-
+ ret = ldap_extended_operation(ld,
+ LDAP_EXOP_MODIFY_PASSWD,
+ &control, NULL, NULL,
+ &msgid);
if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "password change failed!");
+ syslog(LOG_ERR, "ldap_extended_operation() failed. (%d)", ret);
+ ret = KRB5_KPASSWD_HARDERROR;
+ goto done;
+ }
+
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+
+ ret = ldap_result(ld, msgid, 1, &tv, &res);
+ if (ret == -1) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &rc);
+ syslog(LOG_ERR, "ldap_result() failed. (%d)", rc);
+ ret = KRB5_KPASSWD_HARDERROR;
+ goto done;
+ }
+
+ ret = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
+ if(ret != LDAP_SUCCESS) {
+ syslog(LOG_ERR, "ldap_parse_extended_result() failed.");
+ ldap_msgfree(res);
+ ret = KRB5_KPASSWD_HARDERROR;
+ goto done;
+ }
+ if (retoid || retdata) {
+ syslog(LOG_ERR, "ldap_parse_extended_result() returned data, but we don't handle it yet.");
+ }
+
+ ret = ldap_parse_result(ld, res, &rc, NULL, &err, NULL, &srvctrl, 0);
+ if(ret != LDAP_SUCCESS) {
+ syslog(LOG_ERR, "ldap_parse_result() failed.");
ret = KRB5_KPASSWD_HARDERROR;
goto done;
+ }
+ if (rc != LDAP_SUCCESS) {
+ ret = KRB5_KPASSWD_SOFTERROR;
+ if (rc != LDAP_CONSTRAINT_VIOLATION) {
+ ret = KRB5_KPASSWD_HARDERROR;
+ }
+ }
+ if (err) {
+ syslog(LOG_ERR, "ldap_parse_result(): [%s]", err);
+ ldap_memfree(err);
}
- /* TODO: interpret retdata so that we can give back meaningful errors */
+ if (srvctrl) {
+
+ LDAPControl *pprc = NULL;
+ int i;
+
+ for (i = 0; srvctrl[i]; i++) {
+ if (0 == strcmp(srvctrl[i]->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE)) {
+ pprc = srvctrl[i];
+ }
+ }
+ if (pprc) {
+ sctrl = ber_init(&pprc->ldctl_value);
+ }
+
+ if (sctrl) {
+ /*
+ * PasswordPolicyResponseValue ::= SEQUENCE {
+ * warning [0] CHOICE OPTIONAL {
+ * timeBeforeExpiration [0] INTEGER (0 .. maxInt),
+ * graceLoginsRemaining [1] INTEGER (0 .. maxInt) }
+ * error [1] ENUMERATED OPTIONAL {
+ * passwordExpired (0),
+ * accountLocked (1),
+ * changeAfterReset (2),
+ * passwordModNotAllowed (3),
+ * mustSupplyOldPassword (4),
+ * invalidPasswordSyntax (5),
+ * passwordTooShort (6),
+ * passwordTooYoung (7),
+ * passwordInHistory (8) } }
+ */
+
+ ber_tag_t rtag, btag;
+ ber_int_t bint;
+ rtag = ber_scanf(sctrl, "{t", &btag);
+ if (btag == LDAP_TAG_PWP_WARNING) {
+ rtag = ber_scanf(sctrl, "{ti}", &btag, &bint);
+ if (btag == LDAP_TAG_PWP_SECSLEFT) {
+ asprintf(&exterr2, " (%d seconds left before password expires)", bint);
+ } else {
+ asprintf(&exterr2, " (%d grace logins remaining)", bint);
+ }
+ if (!exterr2) {
+ syslog(LOG_ERR, "exterr2: OOM?");
+ }
+ rtag = ber_scanf(sctrl, "t", &btag);
+ }
+ if (btag == LDAP_TAG_PWP_ERROR) {
+ rtag = ber_scanf(sctrl, "e", &bint);
+ switch(bint) {
+ case 0:
+ asprintf(&exterr1, " Err%d: Password Expired.", bint);
+ break;
+ case 1:
+ asprintf(&exterr1, " Err%d: Account locked.", bint);
+ break;
+ case 2:
+ asprintf(&exterr1, " Err%d: Password changed after reset.", bint);
+ break;
+ case 3:
+ asprintf(&exterr1, " Err%d: Password change not allowed.", bint);
+ break;
+ case 4:
+ asprintf(&exterr1, " Err%d: [Shouldn't happen].", bint);
+ break;
+ case 5:
+ asprintf(&exterr1, " Err%d: Password too simple.", bint);
+ break;
+ case 6:
+ asprintf(&exterr1, " Err%d: Password too short.", bint);
+ break;
+ case 7:
+ asprintf(&exterr1, " Err%d: Too soon to change password.", bint);
+ break;
+ case 8:
+ asprintf(&exterr1, " Err%d: Password reuse not permitted.", bint);
+ break;
+ default:
+ asprintf(&exterr1, " Err%d: Unknown Errorcode.", bint);
+ break;
+ }
+ if (!exterr1) {
+ syslog(LOG_ERR, "exterr1: OOM?");
+ }
+ }
+ }
+ }
+
+ if (ret != LDAP_SUCCESS) {
+ syslog(LOG_ERR, "password change failed!");
+ asprintf(errstr, "Password change, Failed.%s%s", exterr1?exterr1:"", exterr2?exterr2:"");
+ } else {
+ syslog(LOG_ERR, "password change succeeded!");
+ asprintf(errstr, "Password change, Succeeded.%s%s", exterr1?exterr1:"", exterr2?exterr2:"");
+ }
done:
- if (userdn) free(userdn);
if (ctrl) ber_free(ctrl, 1);
+ if (sctrl) ber_free(sctrl, 1);
+ if (srvctrl) ldap_controls_free(srvctrl);
+ if (res) ldap_msgfree(res);
+ if (exterr1) free(exterr1);
+ if (exterr2) free(exterr2);
+ if (userdn) free(userdn);
if (ld) ldap_unbind_ext_s(ld, NULL, NULL);
if (ldap_uri) free(ldap_uri);
if (tmp_file) {
@@ -482,6 +660,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
*replen = 0;
+ result_string = NULL;
auth_context = NULL;
krep.length = 0;
krep.data = NULL;
@@ -508,14 +687,14 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
}
break;
default:
- result_string = "Invalid remopte IP address";
+ result_string = strdup("Invalid remopte IP address");
result_err = KRB5_KPASSWD_MALFORMED;
syslog(LOG_ERR, "%s", result_string);
goto done;
}
if (buflen < 4) {
- result_string = "Request truncated";
+ result_string = strdup("Request truncated");
result_err = KRB5_KPASSWD_MALFORMED;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -524,7 +703,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
reqlen = (buf[0] << 8) + buf[1];
if (reqlen != buflen) {
- result_string = "Unmatching request length";
+ result_string = strdup("Unmatching request length");
result_err = KRB5_KPASSWD_MALFORMED;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -533,7 +712,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
verno = (buf[2] << 8) + buf[3];
if (verno != 1) {
- result_string = "Unsupported version";
+ result_string = strdup("Unsupported version");
result_err = KRB5_KPASSWD_BAD_VERSION;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -541,7 +720,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
kreq.length = (buf[4] << 8) + buf[5];
if (kreq.length > (buflen - 6)) {
- result_string = "Request truncated";
+ result_string = strdup("Request truncated");
result_err = KRB5_KPASSWD_MALFORMED;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -550,7 +729,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_init_context(&context);
if (krberr) {
- result_string = "Failed to init kerberos context";
+ result_string = strdup("Failed to init kerberos context");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -558,7 +737,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_get_default_realm(context, &realm_name);
if (krberr) {
- result_string = "Failed to get default realm name";
+ result_string = strdup("Failed to get default realm name");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s", result_string);
goto done;
@@ -566,7 +745,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_auth_con_init(context, &auth_context);
if (krberr) {
- result_string = "Unable to init auth context";
+ result_string = strdup("Unable to init auth context");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -576,7 +755,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_auth_con_setflags(context, auth_context,
KRB5_AUTH_CONTEXT_DO_SEQUENCE);
if (krberr) {
- result_string = "Unable to init auth context";
+ result_string = strdup("Unable to init auth context");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -587,7 +766,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
strlen(realm_name), realm_name,
"kadmin", "changepw", NULL);
if (krberr) {
- result_string = "Unable to build principal";
+ result_string = strdup("Unable to build principal");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -596,7 +775,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_kt_resolve(context, keytab_name, &keytab);
if (krberr) {
- result_string = "Unable to retrieve keytab";
+ result_string = strdup("Unable to retrieve keytab");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -606,7 +785,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_rd_req(context, &auth_context, &kreq,
kprincpw, keytab, NULL, &ticket);
if (krberr) {
- result_string = "Unable to read request";
+ result_string = strdup("Unable to read request");
result_err = KRB5_KPASSWD_AUTHERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -618,7 +797,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
* the password have been successfully changed */
krberr = krb5_mk_rep(context, auth_context, &krep);
if (krberr) {
- result_string = "Failed to to build reply";
+ result_string = strdup("Failed to to build reply");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -627,7 +806,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
/* verify that this is an AS_REQ ticket */
if (!(ticket->enc_part2->flags & TKT_FLG_INITIAL)) {
- result_string = "Ticket must be derived from a password";
+ result_string = strdup("Ticket must be derived from a password");
result_err = KRB5_KPASSWD_AUTHERROR;
syslog(LOG_ERR, "%s", result_string);
goto kpreply;
@@ -636,7 +815,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_unparse_name(context, ticket->enc_part2->client,
&client_name);
if (krberr) {
- result_string = "Unable to parse client name";
+ result_string = strdup("Unable to parse client name");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s", result_string);
goto kpreply;
@@ -644,7 +823,7 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
krberr = krb5_auth_con_setaddrs(context, auth_context, NULL, &rkaddr);
if (krberr) {
- result_string = "Failed to set client address";
+ result_string = strdup("Failed to set client address");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
@@ -659,24 +838,22 @@ void handle_krb_packets(uint8_t *buf, ssize_t buflen,
* requires the local address (from kadmin code) */
krberr = krb5_rd_priv(context, auth_context, &kenc, &kdec, &replay);
if (krberr) {
- result_string = "Failed to decrypt password";
+ result_string = strdup("Failed to decrypt password");
result_err = KRB5_KPASSWD_HARDERROR;
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
goto kpreply;
}
- if (debug > 0) {
+ if (debug > 100) {
syslog(LOG_ERR, "Client %s trying to set password [%*s]",
client_name, kdec.length, kdec.data);
}
/* Actually try to change the password */
- result_err = ldap_pwd_change(client_name, realm_name, kdec);
- if (result_err != KRB5_KPASSWD_SUCCESS) {
- result_string = "Generic error occurred while changing password";
- } else {
- result_string = "";
+ result_err = ldap_pwd_change(client_name, realm_name, kdec, &result_string);
+ if (result_string == NULL) {
+ result_string = strdup("Server Error");
}
/* make sure password is cleared off before we free the memory */
@@ -700,7 +877,7 @@ kpreply:
/* we listen on ANYADDR, use this retrieve the right address */
krberr = krb5_os_localaddr(context, &lkaddr);
if (krberr) {
- result_string = "Failed to retrieve local address";
+ result_string = strdup("Failed to retrieve local address");
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
goto done;
@@ -708,7 +885,7 @@ kpreply:
krberr = krb5_auth_con_setaddrs(context, auth_context, lkaddr[0], NULL);
if (krberr) {
- result_string = "Failed to set local address";
+ result_string = strdup("Failed to set local address");
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
goto done;
@@ -716,7 +893,7 @@ kpreply:
krberr = krb5_mk_priv(context, auth_context, &kdec, &kenc, &replay);
if (krberr) {
- result_string = "Failed to encrypt reply message";
+ result_string = strdup("Failed to encrypt reply message");
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
/* encryption was unsuccessful, let's return a krb error */
@@ -734,7 +911,7 @@ kpreply:
krb5err.susec = 0;
krberr = krb5_timeofday(context, &krb5err.stime);
if (krberr) {
- result_string = "Failed to set time of day";
+ result_string = strdup("Failed to set time of day");
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
goto done;
@@ -744,7 +921,7 @@ kpreply:
krb5err.e_data = kdec;
krberr = krb5_mk_error(context, &krb5err, &kenc);
if (krberr) {
- result_string = "Failed to build error message";
+ result_string = strdup("Failed to build error message");
syslog(LOG_ERR, "%s: %s", result_string,
krb5_get_error_message(context, krberr));
goto done;
@@ -774,6 +951,7 @@ kpreply:
*replen = replylen;
done:
+ if (result_string) free(result_string);
if (auth_context) krb5_auth_con_free(context, auth_context);
if (kprincpw) krb5_free_principal(context, kprincpw);
if (krep.length) free(krep.data);
@@ -787,6 +965,7 @@ pid_t handle_conn(int fd, int type)
{
int mfd, tcp;
pid_t pid;
+ char addrto6[INET6_ADDRSTRLEN+1];
char address[INET6_ADDRSTRLEN+1];
uint8_t request[1500];
ssize_t reqlen;
@@ -809,17 +988,38 @@ pid_t handle_conn(int fd, int type)
return -1;
}
} 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,
- address, INET6_ADDRSTRLEN+1,
+ addrto6, INET6_ADDRSTRLEN+1,
NULL, 0, NI_NUMERICHOST);
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
* are finished on the active client.
* the password change may be slow and pam_krb5 sends up to 3 UDP
@@ -834,15 +1034,17 @@ pid_t handle_conn(int fd, int type)
return 0;
}
- reqlen = recvfrom(mfd, request, sizeof(request), 0,
- (struct sockaddr *)&from, &fromlen);
- if (reqlen <= 0) {
- syslog(LOG_ERR, "Error receiving request (%d) %s",
- errno, strerror(errno));
- if (tcp) close(mfd);
- return -1;
+ /* now read data if it was a TCP connection */
+ if (tcp) {
+ reqlen = recvfrom(mfd, request, sizeof(request), 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (reqlen <= 0) {
+ syslog(LOG_ERR, "Error receiving request (%d) %s",
+ errno, strerror(errno));
+ close(mfd);
+ return -1;
+ }
}
-
#if 1
/* handle kerberos and ldap operations in childrens */
pid = fork();
@@ -860,6 +1062,7 @@ pid_t handle_conn(int fd, int type)
#endif
/* children */
+ if (debug > 0) syslog(LOG_ERR, "Servicing %s", address);
/* TCP packets prepend the lenght as a 32bit network order field,
* this information seem to be just redundant, so let's simply
@@ -874,13 +1077,13 @@ pid_t handle_conn(int fd, int type)
if (tcp) {
sendret = sendto(mfd, reply, replen, 0, NULL, 0);
} else {
- sendret = sendto(mfd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
+ sendret = sendto(fd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
}
if (sendret == -1) {
syslog(LOG_ERR, "Error sending reply (%d)", errno);
}
}
- close(mfd);
+ if (tcp) close(mfd);
exit(0);
}
@@ -895,7 +1098,7 @@ int main(int argc, char *argv[])
int pfdtype[4];
int nfds;
int ret;
- char *key;
+ char *env;
/* log to syslog */
openlog("kpasswd", LOG_PID, LOG_DAEMON);
@@ -935,15 +1138,21 @@ int main(int argc, char *argv[])
exit(0);
}
- key = getenv("KRB5_KTNAME");
- if (!key) {
- key = DEFAULT_KEYTAB;
+ /* source evn vars */
+ env = getenv("KRB5_KTNAME");
+ if (!env) {
+ env = DEFAULT_KEYTAB;
}
- keytab_name = strdup(key);
+ keytab_name = strdup(env);
if (!keytab_name) {
syslog(LOG_ERR, "Out of memory!");
}
+ env = getenv("IPA_KPASSWD_DEBUG");
+ if (env) {
+ debug = strtol(env, NULL, 0);
+ }
+
/* set hints */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
@@ -1026,6 +1235,8 @@ int main(int argc, char *argv[])
/* check for children exiting */
cid = waitpid(-1, &cstatus, WNOHANG);
if (cid != -1 && cid != 0) {
+ if (debug > 0)
+ syslog(LOG_ERR, "pid %d completed operations!\n", cid);
remove_blacklist(cid);
}
}