summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipa-install/README21
-rw-r--r--ipa-install/share/bind.zone.db.template (renamed from ipa-server/ipa-install/share/bind.zone.db.template)0
-rw-r--r--ipa-install/share/fedora-ds.init.patch (renamed from ipa-server/ipa-install/share/fedora-ds.init.patch)0
-rw-r--r--ipa-install/share/krb5.conf.template42
-rw-r--r--ipa-kpasswd/Makefile5
-rw-r--r--ipa-kpasswd/README2
-rw-r--r--ipa-kpasswd/ipa_kpasswd.c629
-rw-r--r--ipa-server/ipa-install/freeipa-setup-20070713.patch288
-rw-r--r--ipa-server/ipa-install/share/default-aci.ldif6
-rw-r--r--ipa-server/ipaserver/krbinstance.py10
10 files changed, 999 insertions, 4 deletions
diff --git a/ipa-install/README b/ipa-install/README
new file mode 100644
index 00000000..31e7375f
--- /dev/null
+++ b/ipa-install/README
@@ -0,0 +1,21 @@
+
+Required packages:
+
+krb5-server
+fedora-ds-base
+openldap-clients
+krb5-server-ldap
+cyrus-sasl-gssapi
+
+
+Installation example:
+
+TEMPORARY: (until fedora ds scripts are fixed)
+please use the fedora-ds.init.patch under share/ to patch your init scripts before
+running ipa-server-install
+
+cd ipa-install
+make install
+cd ..
+/usr/sbin/ipa-server-install -u fds -r FREEIPA.ORG -p freeipa -m ipafree
+
diff --git a/ipa-server/ipa-install/share/bind.zone.db.template b/ipa-install/share/bind.zone.db.template
index e846c4f2..e846c4f2 100644
--- a/ipa-server/ipa-install/share/bind.zone.db.template
+++ b/ipa-install/share/bind.zone.db.template
diff --git a/ipa-server/ipa-install/share/fedora-ds.init.patch b/ipa-install/share/fedora-ds.init.patch
index 88a04fc2..88a04fc2 100644
--- a/ipa-server/ipa-install/share/fedora-ds.init.patch
+++ b/ipa-install/share/fedora-ds.init.patch
diff --git a/ipa-install/share/krb5.conf.template b/ipa-install/share/krb5.conf.template
new file mode 100644
index 00000000..23a24703
--- /dev/null
+++ b/ipa-install/share/krb5.conf.template
@@ -0,0 +1,42 @@
+[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+[libdefaults]
+ default_realm = $REALM
+ dns_lookup_realm = true
+ dns_lookup_kdc = true
+ ticket_lifetime = 24h
+ forwardable = yes
+
+[realms]
+ $REALM = {
+ kdc = $FQDN:88
+ admin_server = $FQDN:749
+ default_domain = $DOMAIN
+}
+
+[domain_realm]
+ .$DOMAIN = $REALM
+ $DOMAIN = $REALM
+
+[appdefaults]
+ pam = {
+ debug = false
+ ticket_lifetime = 36000
+ renew_lifetime = 36000
+ forwardable = true
+ krb4_convert = false
+ }
+
+[dbmodules]
+ $REALM = {
+ db_library = kldap
+ ldap_servers = ldap://127.0.0.1/
+ ldap_kerberos_container_dn = cn=kerberos,$SUFFIX
+ ldap_kdc_dn = uid=kdc,cn=kerberos,$SUFFIX
+ ldap_kadmind_dn = uid=kdc,cn=kerberos,$SUFFIX
+ ldap_service_password_file = /var/kerberos/krb5kdc/ldappwd
+ }
+
diff --git a/ipa-kpasswd/Makefile b/ipa-kpasswd/Makefile
new file mode 100644
index 00000000..efdaa16b
--- /dev/null
+++ b/ipa-kpasswd/Makefile
@@ -0,0 +1,5 @@
+all:
+ gcc ipa_kpasswd.c -I/usr/include -lkrb5 -llber -lldap -g -o ipa_kpasswd
+
+install:
+ cp -f ipa_kpasswd /usr/local/sbin/
diff --git a/ipa-kpasswd/README b/ipa-kpasswd/README
new file mode 100644
index 00000000..c0a2767a
--- /dev/null
+++ b/ipa-kpasswd/README
@@ -0,0 +1,2 @@
+This is an implementation of the RFC3244 kpasswd protocol.
+It is used to proxy password change operations to Directory Server.
diff --git a/ipa-kpasswd/ipa_kpasswd.c b/ipa-kpasswd/ipa_kpasswd.c
new file mode 100644
index 00000000..35503ae9
--- /dev/null
+++ b/ipa-kpasswd/ipa_kpasswd.c
@@ -0,0 +1,629 @@
+
+/* Kpasswd-LDAP proxy */
+
+/* (C) Simo Sorce */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <krb5.h>
+#include <ldap.h>
+#include <sasl/sasl.h>
+
+#define KPASSWD_PORT 464
+#define KPASSWD_TCP 1
+#define KPASSWD_UDP 2
+
+int debug = 1;
+char *srv_pri_name = "kadmin/changepw";
+char *keytab_name = "FILE:/var/kerberos/krb5kdc/kpasswd.keytab";
+char *realm_name = "BLUEBOX.REDHAT.COM";
+char *ldap_uri = "ldap://rc1.bluebox.redhat.com:389";
+
+int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
+{
+ sasl_interact_t **in = sit;
+ int i, ret = LDAP_OTHER;
+
+ if (!ld) return LDAP_PARAM_ERROR;
+
+ for (i = 0; in[i] && in[i]->id != SASL_CB_LIST_END; i++) {
+ switch(in[i]->id) {
+ case SASL_CB_USER:
+ in[i]->result = srv_pri_name;
+ in[i]->len = strlen(srv_pri_name);
+ ret = LDAP_SUCCESS;
+ break;
+ case SASL_CB_GETREALM:
+ in[i]->result = realm_name;
+ in[i]->len = strlen(realm_name);
+ ret = LDAP_SUCCESS;
+ break;
+ default:
+ if (debug > 0) {
+ fprintf(stderr,
+ "Unhandled SASL int. option %d\n",
+ in[i]->id);
+ }
+ in[i]->result = NULL;
+ in[i]->len = 0;
+ ret = LDAP_OTHER;
+ }
+ }
+ return ret;
+}
+
+int ldap_pwd_change(char *client_name, krb5_data pwd)
+{
+ int id, version;
+ LDAP *ld = NULL;
+ BerElement *ctrl = NULL;
+ struct berval control;
+ struct berval newpw;
+ char *userdn = NULL;
+ int ret;
+
+ newpw.bv_len = pwd.length;
+ newpw.bv_val = pwd.data;
+
+ /* connect to ldap server */
+ /* TODO: support referrals ? */
+ ret = ldap_initialize(&ld, ldap_uri);
+ if(ret != LDAP_SUCCESS) {
+ fprintf(stderr, "Unable to connect to ldap server");
+ ret = -1;
+ goto done;
+ }
+
+ version = LDAP_VERSION3;
+ ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (ret != LDAP_OPT_SUCCESS) {
+ fprintf(stderr, "Unable to set ldap protocol version");
+ ret = -1;
+ goto done;
+ }
+
+ ret = ldap_sasl_interactive_bind_s(ld,
+ NULL, "GSSAPI",
+ NULL, NULL,
+ LDAP_SASL_AUTOMATIC,
+ ldap_sasl_interact, NULL);
+ if (ret != LDAP_SUCCESS) {
+ fprintf(stderr, "Unable to bind to ldap server");
+ ret = -1;
+ goto done;
+ }
+
+ /* find user dn */
+
+ /* build password change control */
+ ctrl = ber_alloc_t(LBER_USE_DER);
+ if (!ctrl) {
+ fprintf(stderr, "Out of memory!\n");
+ ret = -1;
+ goto done;
+ }
+ ber_printf(ctrl, "{tstON}",
+ LDAP_TAG_EXOP_MODIFY_PASSWD_ID, userdn,
+ LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw);
+
+ ret = ber_flatten2(ctrl, &control, 0);
+ if (ret < 0) {
+ fprintf(stderr, "ber flattening failed!\n");
+ ret = -1;
+ goto done;
+ }
+
+ /* perform poassword change */
+ ret = ldap_extended_operation(ld, LDAP_EXOP_MODIFY_PASSWD,
+ &control, NULL, NULL, &id);
+done:
+ if (ctrl) ber_free(ctrl, 1);
+ if (ld)
+ return ret;
+}
+
+void handle_krb_packets(uint8_t *buf, ssize_t buflen,
+ struct sockaddr_in *from,
+ uint8_t **repbuf, ssize_t *replen)
+{
+ krb5_auth_context auth_context;
+ krb5_context context;
+ krb5_keytab keytab;
+ krb5_principal kprincpw;
+ krb5_ticket *ticket;
+ krb5_address **lkaddr, rkaddr;
+ krb5_data kreq, krep, kenc, kdec;
+ krb5_replay_data replay;
+ krb5_error krb5err;
+ int krberr, err;
+ struct sockaddr_in laddr, raddr;
+ socklen_t addrlen;
+ size_t reqlen;
+ size_t verno;
+ char *client_name;
+ char *result_string;
+ int result_err;
+ uint8_t *reply;
+ ssize_t replylen;
+
+ *replen = 0;
+
+ auth_context = NULL;
+ krep.length = 0;
+ krep.data = NULL;
+ kprincpw = NULL;
+ ticket = NULL;
+ lkaddr = NULL;
+
+ rkaddr.addrtype = ADDRTYPE_INET;
+ rkaddr.length = sizeof(from->sin_addr);
+ rkaddr.contents = (krb5_octet *) &from->sin_addr;
+
+ if (buflen < 4) {
+ result_string = "Request truncated";
+ result_err = KRB5_KPASSWD_MALFORMED;
+ fprintf(stderr, "%s\n", result_string);
+ goto done;
+ }
+
+ reqlen = (buf[0] << 8) + buf[1];
+
+ if (reqlen != buflen) {
+ result_string = "Unmatching request length";
+ result_err = KRB5_KPASSWD_MALFORMED;
+ fprintf(stderr, "%s\n", result_string);
+ goto done;
+ }
+
+ verno = (buf[2] << 8) + buf[3];
+
+ if (verno != 1) {
+ result_string = "Unsupported version";
+ result_err = KRB5_KPASSWD_BAD_VERSION;
+ fprintf(stderr, "%s\n", result_string);
+ goto done;
+ }
+
+ kreq.length = (buf[4] << 8) + buf[5];
+ if (kreq.length > (buflen - 6)) {
+ result_string = "Request truncated";
+ result_err = KRB5_KPASSWD_MALFORMED;
+ fprintf(stderr, "%s\n", result_string);
+ goto done;
+ }
+ kreq.data = &buf[6];
+
+ krberr = krb5_init_context(&context);
+ if (krberr) {
+ result_string = "Failed to init kerberos context";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s\n", result_string);
+ goto done;
+ }
+
+ krberr = krb5_auth_con_init(context, &auth_context);
+ if (krberr) {
+ result_string = "Unable to init auth context";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_auth_con_setflags(context, auth_context,
+ KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+ if (krberr) {
+ result_string = "Unable to init auth context";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_build_principal(context, &kprincpw,
+ strlen(realm_name), realm_name,
+ "kadmin", "changepw", NULL);
+ if (krberr) {
+ result_string = "Unable to build principal";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_kt_resolve(context, keytab_name, &keytab);
+ if (krberr) {
+ result_string = "Unable to retrieve keytab";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_rd_req(context, &auth_context, &kreq,
+ kprincpw, keytab, NULL, &ticket);
+ if (krberr) {
+ result_string = "Unable to read request";
+ result_err = KRB5_KPASSWD_AUTHERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ /* build the AP Reply before actually changing the password
+ * this minimize the risk of a fatal error occurring _after_
+ * the password have been successfully changed */
+ krberr = krb5_mk_rep(context, auth_context, &krep);
+ if (krberr) {
+ result_string = "Failed to to build reply";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ /* 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_err = KRB5_KPASSWD_AUTHERROR;
+ fprintf(stderr, "%s\n", result_string);
+ goto kpreply;
+ }
+
+ krberr = krb5_unparse_name(context, ticket->enc_part2->client,
+ &client_name);
+ if (krberr) {
+ result_string = "Unable to parse client name";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s\n", result_string);
+ goto kpreply;
+ }
+
+ krberr = krb5_auth_con_setaddrs(context, auth_context, NULL, &rkaddr);
+ if (krberr) {
+ result_string = "Failed to set client address";
+ result_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto kpreply;
+ }
+
+ /* decrypt the new password */
+ kenc.length = reqlen - kreq.length - 6;
+ kenc.data = kreq.data + kreq.length;
+
+ /* rd_priv needs the remote address while mk_priv (used later)
+ * 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_err = KRB5_KPASSWD_HARDERROR;
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto kpreply;
+ }
+
+ if (debug > 0) {
+ fprintf(stderr, "Client %s trying to set password [%*s]\n",
+ client_name, kdec.length, kdec.data);
+ }
+
+ err = ldap_pwd_change(client_name, kdec);
+
+ /* ok we are done, and the password change was successful! */
+ result_err = KRB5_KPASSWD_SUCCESS;
+ result_string = "";
+
+ /* make sure password is cleared off before we free the memory */
+ memset(kdec.data, 0, kdec.length);
+ free(kdec.data);
+
+kpreply:
+
+ /* set-up the the clear text reply */
+ kdec.length = 2 + strlen(result_string);
+ kdec.data = malloc(kdec.length);
+ if (!kdec.data) {
+ fprintf(stderr, "Out of memory!\n");
+ goto done;
+ }
+
+ kdec.data[0] = (result_err >> 8) & 0xff;
+ kdec.data[1] = result_err & 0xff;
+ memcpy(&kdec.data[2], result_string, strlen(result_string));
+
+ /* 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";
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_auth_con_setaddrs(context, auth_context, lkaddr[0], NULL);
+ if (krberr) {
+ result_string = "Failed to set local address";
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krberr = krb5_mk_priv(context, auth_context, &kdec, &kenc, &replay);
+ if (krberr) {
+ result_string = "Failed to encrypt reply message";
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ /* encryption was unsuccessful, let's return a krb error */
+
+ /* the ap data is no more useful */
+ free(krep.data);
+ krep.length = 0;
+
+ /* build a krberror encrypted paylod */
+ krb5err.error = KRB5_CHPW_FAIL;
+ krb5err.server = kprincpw;
+ krb5err.client = NULL;
+ krb5err.ctime = 0;
+ krb5err.cusec = 0;
+ krb5err.susec = 0;
+ krberr = krb5_timeofday(context, &krb5err.stime);
+ if (krberr) {
+ result_string = "Failed to set time of day";
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
+ krb5err.text.length = 0;
+ krb5err.e_data = kdec;
+ krberr = krb5_mk_error(context, &krb5err, &kenc);
+ if (krberr) {
+ result_string = "Failed to build error message";
+ fprintf(stderr, "%s: %s\n", result_string,
+ krb5_get_error_message(context, krberr));
+ goto done;
+ }
+ }
+
+ replylen = 6 + krep.length + kenc.length;
+ reply = malloc(replylen);
+ if (!reply) {
+ fprintf(stderr, "Out of memory!\n");
+ goto done;
+ }
+ *repbuf = reply;
+
+ reply[0] = (replylen >> 8) & 0xff;
+ reply[1] = replylen & 0xff;
+ reply[2] = 0x00;
+ reply[3] = 0x01;
+ reply[4] = (krep.length >> 8) & 0xff;
+ reply[5] = krep.length & 0xff;
+
+ if (krep.length) {
+ memcpy(&reply[6], krep.data, krep.length);
+ }
+ memcpy(&reply[6 + krep.length], kenc.data, kenc.length);
+
+ *replen = replylen;
+
+done:
+ if (auth_context) krb5_auth_con_free(context, auth_context);
+ if (kprincpw) krb5_free_principal(context, kprincpw);
+ if (krep.length) free(krep.data);
+ if (ticket) krb5_free_ticket(context, ticket);
+ if (kdec.length) free(kdec.data);
+ if (lkaddr) krb5_free_addresses(context, lkaddr);
+ krb5_free_context(context);
+}
+
+pid_t handle_conn(int fd, int type)
+{
+ int mfd;
+ pid_t pid;
+ uint8_t request[1500];
+ ssize_t reqlen;
+ uint8_t *reply;
+ ssize_t replen;
+ struct sockaddr_in from;
+ socklen_t fromlen;
+
+ fromlen = sizeof(from);
+
+ /* receive request */
+ if (type == KPASSWD_TCP) {
+
+ mfd = accept(fd, (struct sockaddr *)&from, &fromlen);
+ if (mfd == -1) {
+ fprintf(stderr, "Accept failed with error (%d) %s\n",
+ errno, strerror(errno));
+ return -1;
+ }
+ } else {
+ mfd = fd;
+ }
+
+ reqlen = recvfrom(mfd, request, sizeof(request), 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (reqlen <= 0) {
+ fprintf(stderr, "Error receiving request (%d) %s\n",
+ errno, strerror(errno));
+ if (type == KPASSWD_TCP) close(mfd);
+ return -1;
+ }
+
+ if (debug > 0) {
+ uint32_t host = ntohl(from.sin_addr.s_addr);
+ uint16_t port = ntohs(from.sin_port);
+ fprintf(stderr,
+ "Connection from %d.%d.%d.%d:%d\n",
+ (host & 0xff000000) >> 24,
+ (host & 0x00ff0000) >> 16,
+ (host & 0x0000ff00) >> 8,
+ host & 0x000000ff,
+ port);
+ }
+
+#if 1
+ /* handle kerberos and ldap operations in childrens */
+ pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Fork failed with error (%d) %s\n",
+ errno, strerror(errno));
+ if (type == KPASSWD_TCP) close(mfd);
+ return 0;
+ }
+ if (pid != 0) { /* parent */
+ if (type == KPASSWD_TCP) close(mfd);
+ return pid;
+ }
+#endif
+ /* children */
+ handle_krb_packets(request, reqlen, &from, &reply, &replen);
+
+ if (replen) { /* we have something to reply */
+ if (type == KPASSWD_TCP) {
+ sendto(mfd, reply, replen, 0, NULL, 0);
+ } else {
+ sendto(mfd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
+ }
+ }
+ close(mfd);
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ struct sockaddr_in addr;
+ int tcp_s, udp_s;
+ int tru = 1;
+ int ret;
+
+ tcp_s = socket(AF_INET, SOCK_STREAM, 0);
+ if (tcp_s == -1) {
+ fprintf(stderr, "Unable to create TCP socket\n");
+ exit(1);
+ }
+
+ udp_s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (udp_s == -1) {
+ fprintf(stderr, "Unable to create UDP socket\n");
+ close(tcp_s);
+ exit(1);
+ }
+
+ /* make sockets immediately reusable */
+ ret = setsockopt(tcp_s, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&tru, sizeof(tru));
+ if (ret == -1) {
+ fprintf(stderr,
+ "Unable to set SO_REUSEADDR for the TCP socket (%d) %s\n",
+ errno, strerror(errno));
+ close(tcp_s);
+ close(udp_s);
+ exit(2);
+ }
+
+ ret = setsockopt(udp_s, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&tru, sizeof(tru));
+ if (ret == -1) {
+ fprintf(stderr,
+ "Unable to set SO_REUSEADDR for the UDP socket (%d) %s\n",
+ errno, strerror(errno));
+ close(tcp_s);
+ close(udp_s);
+ exit(2);
+ }
+
+ /* bind sockets */
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(KPASSWD_PORT);
+
+ ret = bind(tcp_s, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret == -1) {
+ fprintf(stderr,
+ "Unable to bind the TCP kpasswd port (%d) %s\n",
+ errno, strerror(errno));
+ close(tcp_s);
+ close(udp_s);
+ exit(3);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(KPASSWD_PORT);
+
+ ret = bind(udp_s, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret == -1) {
+ fprintf(stderr,
+ "Unable to bind the UDP kpasswd port (%d) %s\n",
+ errno, strerror(errno));
+ close(tcp_s);
+ close(udp_s);
+ exit(3);
+ }
+
+ ret = listen(tcp_s, 5);
+ if (ret == -1) {
+ fprintf(stderr,
+ "Unable to listen oin the TCP socket (%d) %s\n",
+ errno, strerror(errno));
+ close(tcp_s);
+ close(udp_s);
+ exit(4);
+ }
+
+ /* now that sockets are set up, enter the select loop */
+
+ while (1) {
+ int cstatus;
+ fd_set rfd;
+
+ FD_ZERO(&rfd);
+ FD_SET(udp_s, &rfd);
+ FD_SET(tcp_s, &rfd);
+
+ ret = select(udp_s+1, &rfd, NULL, NULL, NULL);
+
+ switch(ret) {
+ case 0:
+ break;
+ case -1:
+ if (errno != EINTR) {
+ fprintf(stderr,
+ "Unexpected error in select (%d) %s\n",
+ errno, strerror(errno));
+ exit(5);
+ }
+ break;
+ default:
+ if (FD_ISSET(tcp_s, &rfd)) {
+ handle_conn(tcp_s, KPASSWD_TCP);
+ break;
+ }
+ if (FD_ISSET(udp_s, &rfd)) {
+ handle_conn(udp_s, KPASSWD_UDP);
+ break;
+ }
+ /* what else?? */
+ fprintf(stderr, "Select returned but no fd ready\n");
+ exit(6);
+ }
+
+ /* check for children exiting */
+ waitpid(-1, &cstatus, WNOHANG);
+ }
+}
diff --git a/ipa-server/ipa-install/freeipa-setup-20070713.patch b/ipa-server/ipa-install/freeipa-setup-20070713.patch
new file mode 100644
index 00000000..5a36eee0
--- /dev/null
+++ b/ipa-server/ipa-install/freeipa-setup-20070713.patch
@@ -0,0 +1,288 @@
+diff -r 5ebd8adc48b8 ipa-install/README
+--- a/ipa-install/README Mon Jul 02 15:51:04 2007 -0400
++++ b/ipa-install/README Fri Jul 13 16:25:05 2007 -0400
+@@ -5,12 +5,17 @@ fedora-ds-base
+ fedora-ds-base
+ openldap-clients
+ krb5-server-ldap
++cyrus-sasl-gssapi
+
+
+ Installation example:
++
++TEMPORARY: (until fedora ds scripts are fixed)
++please use the fedora-ds.init.patch under share/ to patch your init scripts before
++running ipa-server-install
+
+ cd ipa-install
+ make install
+ cd ..
+-/usr/sbin/ipa-server-install -r FREEIPA.ORG -a rc1.freeipa.org -p freeipa -m ipafree
++/usr/sbin/ipa-server-install -u fds -r FREEIPA.ORG -p freeipa -m ipafree
+
+diff -r 5ebd8adc48b8 ipa-install/share/bind.zone.db.template
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/ipa-install/share/bind.zone.db.template Fri Jul 13 16:22:12 2007 -0400
+@@ -0,0 +1,26 @@
++$$ORIGIN $DOMAIN.
++$$TTL 86400
++@ IN SOA $DOMAIN. root.$DOMAIN. (
++ 01 ; serial (d. adams)
++ 3H ; refresh
++ 15M ; retry
++ 1W ; expiry
++ 1D ) ; minimum
++
++ IN NS $HOST
++$HOST IN A $IP
++;
++; ldap servers
++_ldap._tcp IN SRV 0 100 389 $HOST
++
++;kerberos realm
++_kerberos IN TXT $REALM
++
++; kerberos servers
++_kerberos._tcp IN SRV 0 100 88 $HOST
++_kerberos._udp IN SRV 0 100 88 $HOST
++_kerberos-master._tcp IN SRV 0 100 88 $HOST
++_kerberos-master._udp IN SRV 0 100 88 $HOST
++_kpasswd._tcp IN SRV 0 100 88 $HOST
++_kpasswd._udp IN SRV 0 100 88 $HOST
++
+diff -r 5ebd8adc48b8 ipa-install/share/fedora-ds.init.patch
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/ipa-install/share/fedora-ds.init.patch Fri Jul 13 14:45:53 2007 -0400
+@@ -0,0 +1,12 @@
++--- /etc/init.d/fedora-ds.orig 2007-07-06 18:21:30.000000000 -0400
+++++ /etc/init.d/fedora-ds 2007-05-18 19:36:24.000000000 -0400
++@@ -10,6 +10,9 @@
++ # datadir: /var/lib/fedora-ds/slapd-<instance name>
++ #
++
+++# Get config.
+++[ -r /etc/sysconfig/fedora-ds ] && . /etc/sysconfig/fedora-ds
+++
++ # Source function library.
++ if [ -f /etc/rc.d/init.d/functions ] ; then
++ . /etc/rc.d/init.d/functions
+diff -r 5ebd8adc48b8 ipa-install/share/krb5.conf.template
+--- a/ipa-install/share/krb5.conf.template Mon Jul 02 15:51:04 2007 -0400
++++ b/ipa-install/share/krb5.conf.template Fri Jul 13 11:01:36 2007 -0400
+@@ -9,6 +9,13 @@
+ dns_lookup_kdc = true
+ ticket_lifetime = 24h
+ forwardable = yes
++
++[realms]
++ $REALM = {
++ kdc = $FQDN:88
++ admin_server = $FQDN:749
++ default_domain = $DOMAIN
++}
+
+ [domain_realm]
+ .$DOMAIN = $REALM
+@@ -29,7 +36,7 @@
+ ldap_servers = ldap://127.0.0.1/
+ ldap_kerberos_container_dn = cn=kerberos,$SUFFIX
+ ldap_kdc_dn = uid=kdc,cn=kerberos,$SUFFIX
+-; ldap_kadmind_dn = cn=Directory Manager
++ ldap_kadmind_dn = uid=kdc,cn=kerberos,$SUFFIX
+ ldap_service_password_file = /var/kerberos/krb5kdc/ldappwd
+ }
+
+diff -r 5ebd8adc48b8 ipa-install/src/ipa-server-install
+--- a/ipa-install/src/ipa-server-install Mon Jul 02 15:51:04 2007 -0400
++++ b/ipa-install/src/ipa-server-install Fri Jul 13 19:43:13 2007 -0400
+@@ -26,6 +26,7 @@
+
+ VERSION = "%prog .1"
+
++import socket
+ import logging
+ from optparse import OptionParser
+ import ipa.dsinstance
+@@ -37,8 +38,6 @@ def parse_options():
+ help="ds user")
+ parser.add_option("-r", "--realm", dest="realm_name",
+ help="realm name")
+- parser.add_option("-a", "--host-address", dest="host_name",
+- help="host address (name or IP address)")
+ parser.add_option("-p", "--password", dest="password",
+ help="admin password")
+ parser.add_option("-m", "--master-password", dest="master_password",
+@@ -46,8 +45,8 @@ def parse_options():
+
+ options, args = parser.parse_args()
+
+- if not options.realm_name or not options.host_name or not options.password:
+- parser.error("error: password, realm, and host name required")
++ if not options.ds_user or not options.realm_name or not options.password or not options.master_password:
++ parser.error("error: all options are required")
+
+ return options
+
+@@ -56,13 +55,35 @@ def main():
+ format='%(asctime)s %(levelname)s %(message)s',
+ filename='ipa-install.log',
+ filemode='w')
++
+ options = parse_options()
++
++ # check the hostname is correctly configured, it must be as the kldap
++ # utilities just use the hostname as returned by gethostbyname to set
++ # up some of the standard entries
++
++ host_name = socket.gethostname()
++ if len(host_name.split(".")) < 2:
++ print "Invalid hostname <"+host_name+">"
++ print "Check the /etc/hosts file and make sure to have a valid FQDN"
++ return "-Fatal Error-"
++
++ if socket.gethostbyname(host_name) == "127.0.0.1":
++ print "The hostname resolves to the localhost address (127.0.0.1)"
++ print "Please change your /etc/hosts file or your DNS so that the"
++ print "hostname resolves to the ip address of your network interface."
++ print "The KDC service does not listen on 127.0.0.1"
++ return "-Fatal Error-"
++
++ print "The Final KDC Host Name will be: " + host_name
++
+ ds = ipa.dsinstance.DsInstance()
+- ds.create_instance(options.ds_user, options.realm_name, options.host_name, options.password)
++ ds.create_instance(options.ds_user, options.realm_name, host_name, options.password)
+
+ krb = ipa.krbinstance.KrbInstance()
+- krb.create_instance(options.ds_user, options.realm_name, options.host_name, options.password, options.master_password)
+- #restart ds after the krb instance have add the sasl map
++ krb.create_instance(options.ds_user, options.realm_name, host_name, options.password, options.master_password)
++
++ #restart ds after the krb instance have add the sasl map and the ldap keytab
+ ds.restart()
+
+ return 0
+diff -r 5ebd8adc48b8 ipa-install/src/ipa/krbinstance.py
+--- a/ipa-install/src/ipa/krbinstance.py Mon Jul 02 15:51:04 2007 -0400
++++ b/ipa-install/src/ipa/krbinstance.py Fri Jul 13 19:20:41 2007 -0400
+@@ -25,6 +25,9 @@ import logging
+ import logging
+ from random import Random
+ from time import gmtime
++import os
++import pwd
++import socket
+
+ SHARE_DIR = "/usr/share/ipa/"
+
+@@ -32,6 +35,10 @@ def realm_to_suffix(realm_name):
+ s = realm_name.split(".")
+ terms = ["dc=" + x.lower() for x in s]
+ return ",".join(terms)
++
++def host_to_domain(fqdn):
++ s = fqdn.split(".")
++ return ".".join(s[1:])
+
+ def generate_kdc_password():
+ rndpwd = ''
+@@ -75,8 +82,10 @@ class KrbInstance:
+ class KrbInstance:
+ def __init__(self):
+ self.ds_user = None
+- self.realm_name = None
+- self.host_name = None
++ self.fqdn = None
++ self.realm = None
++ self.domain = None
++ self.host = None
+ self.admin_password = None
+ self.master_password = None
+ self.suffix = None
+@@ -85,12 +94,15 @@ class KrbInstance:
+
+ def create_instance(self, ds_user, realm_name, host_name, admin_password, master_password):
+ self.ds_user = ds_user
+- self.realm_name = realm_name.upper()
+- self.host_name = host_name
++ self.fqdn = host_name
++ self.ip = socket.gethostbyname(host_name)
++ self.realm = realm_name.upper()
++ self.host = host_name.split(".")[0]
++ self.domain = host_to_domain(host_name)
+ self.admin_password = admin_password
+ self.master_password = master_password
+
+- self.suffix = realm_to_suffix(self.realm_name)
++ self.suffix = realm_to_suffix(self.realm)
+ self.kdc_password = generate_kdc_password()
+ self.__configure_kdc_account_password()
+
+@@ -99,6 +111,10 @@ class KrbInstance:
+ self.__configure_ldap()
+
+ self.__create_instance()
++
++ self.__create_ds_keytab()
++
++ self.__create_sample_bind_zone()
+
+ self.start()
+
+@@ -120,12 +136,13 @@ class KrbInstance:
+ pwd_fd.close()
+
+ def __setup_sub_dict(self):
+- #FIXME: can DOMAIN be different than REALM ?
+- self.sub_dict = dict(FQHN=self.host_name,
++ self.sub_dict = dict(FQDN=self.fqdn,
++ IP=self.ip,
+ PASSWORD=self.kdc_password,
+ SUFFIX=self.suffix,
+- DOMAIN= self.realm_name.lower(),
+- REALM=self.realm_name)
++ DOMAIN=self.domain,
++ HOST=self.host,
++ REALM=self.realm)
+
+ def __configure_ldap(self):
+
+@@ -153,7 +170,7 @@ class KrbInstance:
+ krb5_fd.close()
+
+ #populate the directory with the realm structure
+- args = ["/usr/kerberos/sbin/kdb5_ldap_util", "-D", "uid=kdc,cn=kerberos,"+self.suffix, "-w", self.kdc_password, "create", "-s", "-r", self.realm_name, "-subtrees", self.suffix, "-sscope", "sub"]
++ args = ["/usr/kerberos/sbin/kdb5_ldap_util", "-D", "uid=kdc,cn=kerberos,"+self.suffix, "-w", self.kdc_password, "create", "-s", "-P", self.master_password, "-r", self.realm, "-subtrees", self.suffix, "-sscope", "sub"]
+ run(args)
+
+ # TODO: NOT called yet, need to find out how to make sure the plugin is available first
+@@ -165,5 +182,28 @@ class KrbInstance:
+ extop_fd.close()
+
+ #add an ACL to let the DS user read the master key
+- args = ["/usr/bin/setfacl", "-m", "u:"+self.ds_user+":r", "/var/kerberos/krb5kdc/.k5."+self.realm_name]
++ args = ["/usr/bin/setfacl", "-m", "u:"+self.ds_user+":r", "/var/kerberos/krb5kdc/.k5."+self.realm]
+ run(args)
++
++ def __create_sample_bind_zone(self):
++ bind_txt = template_file(SHARE_DIR + "bind.zone.db.template", self.sub_dict)
++ [bind_fd, bind_name] = tempfile.mkstemp(".db","sammple.zone.")
++ os.write(bind_fd, bind_txt)
++ os.close(bind_fd)
++ print "Sample zone file for bind has been created in "+bind_name
++
++ def __create_ds_keytab(self):
++ (kwrite, kread, kerr) = os.popen3("/usr/kerberos/sbin/kadmin.local")
++ kwrite.write("addprinc -randkey ldap/"+self.fqdn+"@"+self.realm+"\n")
++ kwrite.flush()
++ kwrite.write("ktadd -k /etc/fedora-ds/ds.keytab ldap/"+self.fqdn+"@"+self.realm+"\n")
++ kwrite.flush()
++ kwrite.close()
++ kread.close()
++ kerr.close()
++
++ cfg_fd = open("/etc/sysconfig/fedora-ds", "a")
++ cfg_fd.write("export KRB5_KTNAME=/etc/fedora-ds/ds.keytab\n")
++ cfg_fd.close()
++ pent = pwd.getpwnam(self.ds_user)
++ os.chown("/etc/sysconfig/fedora-ds", pent.pw_uid, pent.pw_gid)
diff --git a/ipa-server/ipa-install/share/default-aci.ldif b/ipa-server/ipa-install/share/default-aci.ldif
index dc729ceb..8916833c 100644
--- a/ipa-server/ipa-install/share/default-aci.ldif
+++ b/ipa-server/ipa-install/share/default-aci.ldif
@@ -2,7 +2,9 @@
dn: $SUFFIX
changetype: modify
replace: aci
-aci: (targetattr!="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTPassword")(version 3.0; acl "Enable anonymous access"; allow (read, search, compare)userdn="ldap:///anyone";)
+aci: (targetattr!="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTPassword")(version 3.0; acl "Enable anonymous access"; allow (read, search, compare) userdn="ldap:///anyone";)
aci: (targetattr="carLicense ||description ||displayName ||facsimileTelephoneNumber ||homePhone ||homePostalAddress ||initials ||jpegPhoto ||labeledURL ||mail ||mobile ||pager ||photo ||postOfficeBox ||postalAddress ||postalCode ||preferredDeliveryMethod ||preferredLanguage ||registeredAddress ||roomNumber | |secretary ||seeAlso ||st ||street ||telephoneNumber ||telexNumber ||title || userCertificate ||userPassword ||userSMIMECertificate ||x500UniqueIdentifier")(version 3.0; acl "Enable self write for common attributes"; allow (write) userdn="ldap:///self";)
-aci: (targetattr="krbPrincipalKey")(version 3.0; acl "KDC System Account"; allow(read, search,compare)userdn="ldap:///uid=kdc,cn=kerberos,$SUFFIX";)
+aci: (targetattr="krbPrincipalKey")(version 3.0; acl "KDC System Account"; allow (read, search, compare) userdn="ldap:///uid=kdc,cn=kerberos,$SUFFIX";)
aci: (targetattr="*")(version 3.0; acl "Directory Administrators can manage all entries"; allow(all)groupdn="ldap:///cn=Directory Administrators,$SUFFIX";)
+aci: (targetattr="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTPassword")(version 3.0; acl "Kpasswd access to passowrd hashes for passowrd changes"; allow (all) userdn="ldap:///krbprincipalname=kadmin/changepw@$REALM,cn=$REALM,cn=kerberos,$SUFFIX";)
+
diff --git a/ipa-server/ipaserver/krbinstance.py b/ipa-server/ipaserver/krbinstance.py
index 253c506f..131eee35 100644
--- a/ipa-server/ipaserver/krbinstance.py
+++ b/ipa-server/ipaserver/krbinstance.py
@@ -28,7 +28,13 @@ from time import gmtime
import os
import pwd
import socket
-from util import *
+
+SHARE_DIR = "/usr/share/ipa/"
+
+def realm_to_suffix(realm_name):
+ s = realm_name.split(".")
+ terms = ["dc=" + x.lower() for x in s]
+ return ",".join(terms)
def host_to_domain(fqdn):
s = fqdn.split(".")
@@ -155,7 +161,7 @@ class KrbInstance:
def __create_sample_bind_zone(self):
bind_txt = template_file(SHARE_DIR + "bind.zone.db.template", self.sub_dict)
- [bind_fd, bind_name] = tempfile.mkstemp(".db","sample.zone.")
+ [bind_fd, bind_name] = tempfile.mkstemp(".db","sammple.zone.")
os.write(bind_fd, bind_txt)
os.close(bind_fd)
print "Sample zone file for bind has been created in "+bind_name