Example #1
0
/* Used by the slave to update its hash db from* the incr update log.  Must be
 * called with lock held. */
krb5_error_code
ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args)
{
    krb5_db_entry *entry = NULL;
    kdb_incr_update_t *upd = NULL, *fupd;
    int i, no_of_updates;
    krb5_error_code retval;
    krb5_principal dbprinc;
    kdb_last_t errlast, *last;
    char *dbprincstr;
    kdb_log_context *log_ctx;
    kdb_hlog_t *ulog = NULL;

    INIT_ULOG(context);

    no_of_updates = incr_ret->updates.kdb_ulog_t_len;
    upd = incr_ret->updates.kdb_ulog_t_val;
    fupd = upd;

    /* We reset last_sno and last_time to 0, if krb5_db2_db_put_principal or
     * krb5_db2_db_delete_principal fail. */
    errlast.last_sno = (unsigned int)0;
    errlast.last_time.seconds = (unsigned int)0;
    errlast.last_time.useconds = (unsigned int)0;
    last = &errlast;

    retval = krb5_db_open(context, db_args,
                          KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
    if (retval)
        goto cleanup;

    for (i = 0; i < no_of_updates; i++) {
        if (!upd->kdb_commit)
            continue;

        if (upd->kdb_deleted) {
            dbprincstr = k5memdup0(upd->kdb_princ_name.utf8str_t_val,
                                   upd->kdb_princ_name.utf8str_t_len, &retval);
            if (dbprincstr == NULL)
                goto cleanup;

            retval = krb5_parse_name(context, dbprincstr, &dbprinc);
            free(dbprincstr);
            if (retval)
                goto cleanup;

            retval = krb5int_delete_principal_no_log(context, dbprinc);
            krb5_free_principal(context, dbprinc);
            if (retval)
                goto cleanup;
        } else {
            entry = k5alloc(sizeof(krb5_db_entry), &retval);
            if (entry == NULL)
                goto cleanup;

            retval = ulog_conv_2dbentry(context, &entry, upd);
            if (retval)
                goto cleanup;

            retval = krb5int_put_principal_no_log(context, entry);
            krb5_db_free_principal(context, entry);
            if (retval)
                goto cleanup;
        }

        upd++;
    }

    last = &incr_ret->lastentry;

cleanup:
    if (fupd)
        ulog_free_entries(fupd, no_of_updates);

    /* Record a new last serial number and timestamp in the ulog header. */
    ulog->kdb_last_sno = last->last_sno;
    ulog->kdb_last_time = last->last_time;
    ulog_sync_header(ulog);

    return retval;
}
Example #2
0
void
krb5_iprop_prog_1(struct svc_req *rqstp,
		  register SVCXPRT *transp)
{
    union {
	kdb_last_t iprop_get_updates_1_arg;
    } argument;
    char *result;
    bool_t (*_xdr_argument)(), (*_xdr_result)();
    char *(*local)(/* union XXX *, struct svc_req * */);
    char *whoami = "krb5_iprop_prog_1";

    if (!check_iprop_rpcsec_auth(rqstp)) {
	krb5_klog_syslog(LOG_ERR,
			 "authentication attempt failed: %s, RPC authentication flavor %d",
			 inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
			 rqstp->rq_cred.oa_flavor);
	svcerr_weakauth(transp);
	return;
    }

    switch (rqstp->rq_proc) {
    case NULLPROC:
	(void) svc_sendreply(transp, xdr_void,
			     (char *)NULL);
	return;

    case IPROP_GET_UPDATES:
	_xdr_argument = xdr_kdb_last_t;
	_xdr_result = xdr_kdb_incr_result_t;
	local = (char *(*)()) iprop_get_updates_1_svc;
	break;

    case IPROP_FULL_RESYNC:
	_xdr_argument = xdr_void;
	_xdr_result = xdr_kdb_fullresync_result_t;
	local = (char *(*)()) iprop_full_resync_1_svc;
	break;

    default:
	krb5_klog_syslog(LOG_ERR,
			 _("RPC unknown request: %d (%s)"),
			 rqstp->rq_proc, whoami);
	svcerr_noproc(transp);
	return;
    }
    (void) memset((char *)&argument, 0, sizeof (argument));
    if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
	krb5_klog_syslog(LOG_ERR,
			 _("RPC svc_getargs failed (%s)"),
			 whoami);
	svcerr_decode(transp);
	return;
    }
    result = (*local)(&argument, rqstp);

    if (_xdr_result && result != NULL &&
	!svc_sendreply(transp, _xdr_result, result)) {
	krb5_klog_syslog(LOG_ERR,
			 _("RPC svc_sendreply failed (%s)"),
			 whoami);
	svcerr_systemerr(transp);
    }
    if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
	krb5_klog_syslog(LOG_ERR,
			 _("RPC svc_freeargs failed (%s)"),
			 whoami);

	exit(1);
    }

    if (rqstp->rq_proc == IPROP_GET_UPDATES) {
	/* LINTED */
	kdb_incr_result_t *r = (kdb_incr_result_t *)result;

	if (r->ret == UPDATE_OK) {
	    ulog_free_entries(r->updates.kdb_ulog_t_val,
			      r->updates.kdb_ulog_t_len);
	    r->updates.kdb_ulog_t_val = NULL;
	    r->updates.kdb_ulog_t_len = 0;
	}
    }

}
Example #3
0
/*
 * Validate the log file and resync any uncommitted update entries
 * to the principal database.
 *
 * Must be called with lock held.
 */
static krb5_error_code
ulog_check(krb5_context context, kdb_hlog_t *ulog, char **db_args)
{
    XDR                 xdrs;
    krb5_error_code     retval = 0;
    unsigned int        i;
    kdb_ent_header_t    *indx_log;
    kdb_incr_update_t   *upd = NULL;
    kdb_incr_result_t   *incr_ret = NULL;

    ulog->kdb_state = KDB_STABLE;

    for (i = 0; i < ulog->kdb_num; i++) {
        indx_log = (kdb_ent_header_t *)INDEX(ulog, i);

        if (indx_log->kdb_umagic != KDB_ULOG_MAGIC) {
            /*
             * Update entry corrupted we should scream and die
             */
            ulog->kdb_state = KDB_CORRUPT;
            retval = KRB5_LOG_CORRUPT;
            break;
        }

        if (indx_log->kdb_commit == FALSE) {
            ulog->kdb_state = KDB_UNSTABLE;

            incr_ret = (kdb_incr_result_t *)
                malloc(sizeof (kdb_incr_result_t));
            if (incr_ret == NULL) {
                retval = errno;
                goto error;
            }

            upd = (kdb_incr_update_t *)
                malloc(sizeof (kdb_incr_update_t));
            if (upd == NULL) {
                retval = errno;
                goto error;
            }

            (void) memset(upd, 0, sizeof (kdb_incr_update_t));
            xdrmem_create(&xdrs, (char *)indx_log->entry_data,
                          indx_log->kdb_entry_size, XDR_DECODE);
            if (!xdr_kdb_incr_update_t(&xdrs, upd)) {
                retval = KRB5_LOG_CONV;
                goto error;
            }

            incr_ret->updates.kdb_ulog_t_len = 1;
            incr_ret->updates.kdb_ulog_t_val = upd;

            upd->kdb_commit = TRUE;

            /*
             * We don't want to readd this update and just use the
             * existing update to be propagated later on
             */
            ulog_set_role(context, IPROP_NULL);
            retval = ulog_replay(context, incr_ret, db_args);

            /*
             * upd was freed by ulog_replay, we NULL
             * the pointer in case we subsequently break from loop.
             */
            upd = NULL;
            if (incr_ret) {
                free(incr_ret);
                incr_ret = NULL;
            }
            ulog_set_role(context, IPROP_MASTER);

            if (retval)
                goto error;

            /*
             * We flag this as committed since this was
             * the last entry before kadmind crashed, ergo
             * the slaves have not seen this update before
             */
            indx_log->kdb_commit = TRUE;
            retval = ulog_sync_update(ulog, indx_log);
            if (retval)
                goto error;

            ulog->kdb_state = KDB_STABLE;
        }
    }

error:
    if (upd)
        ulog_free_entries(upd, 1);

    free(incr_ret);

    ulog_sync_header(ulog);

    return (retval);
}
Example #4
0
/* Used by the slave to update its hash db from the incr update log. */
krb5_error_code
ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args)
{
    krb5_db_entry *entry = NULL;
    kdb_incr_update_t *upd = NULL, *fupd;
    int i, no_of_updates;
    krb5_error_code retval;
    krb5_principal dbprinc;
    char *dbprincstr;
    kdb_log_context *log_ctx;
    kdb_hlog_t *ulog = NULL;

    INIT_ULOG(context);

    /* Lock the DB before the ulog to avoid deadlock. */
    retval = krb5_db_open(context, db_args,
                          KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
    if (retval)
        return retval;
    retval = krb5_db_lock(context, KRB5_DB_LOCKMODE_EXCLUSIVE);
    if (retval)
        return retval;
    retval = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE);
    if (retval) {
        krb5_db_unlock(context);
        return retval;
    }

    no_of_updates = incr_ret->updates.kdb_ulog_t_len;
    upd = incr_ret->updates.kdb_ulog_t_val;
    fupd = upd;

    for (i = 0; i < no_of_updates; i++) {
        if (!upd->kdb_commit)
            continue;

        /* If (unexpectedly) this update does not follow the last one we
         * stored, discard any previous ulog state. */
        if (ulog->kdb_num != 0 && upd->kdb_entry_sno != ulog->kdb_last_sno + 1)
            reset_header(ulog);

        if (upd->kdb_deleted) {
            dbprincstr = k5memdup0(upd->kdb_princ_name.utf8str_t_val,
                                   upd->kdb_princ_name.utf8str_t_len, &retval);
            if (dbprincstr == NULL)
                goto cleanup;

            retval = krb5_parse_name(context, dbprincstr, &dbprinc);
            free(dbprincstr);
            if (retval)
                goto cleanup;

            retval = krb5int_delete_principal_no_log(context, dbprinc);
            krb5_free_principal(context, dbprinc);
            if (retval == KRB5_KDB_NOENTRY)
                retval = 0;
            if (retval)
                goto cleanup;
        } else {
            entry = k5alloc(sizeof(krb5_db_entry), &retval);
            if (entry == NULL)
                goto cleanup;

            retval = ulog_conv_2dbentry(context, &entry, upd);
            if (retval)
                goto cleanup;

            retval = krb5int_put_principal_no_log(context, entry);
            krb5_db_free_principal(context, entry);
            if (retval)
                goto cleanup;
        }

        retval = store_update(log_ctx, upd);
        if (retval)
            goto cleanup;

        upd++;
    }

cleanup:
    if (fupd)
        ulog_free_entries(fupd, no_of_updates);
    if (retval) {
        reset_header(ulog);
        sync_header(ulog);
    }
    unlock_ulog(context);
    krb5_db_unlock(context);
    return retval;
}
Example #5
0
/*
 * Used by the slave or master (during ulog_check) to update it's hash db from
 * the incr update log.
 *
 * Must be called with lock held.
 */
krb5_error_code
ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args)
{
    krb5_db_entry       *entry = NULL;
    kdb_incr_update_t   *upd = NULL, *fupd;
    int                 i, no_of_updates;
    krb5_error_code     retval;
    krb5_principal      dbprinc = NULL;
    kdb_last_t          errlast;
    char                *dbprincstr = NULL;
    kdb_log_context     *log_ctx;
    kdb_hlog_t          *ulog = NULL;

    INIT_ULOG(context);

    no_of_updates = incr_ret->updates.kdb_ulog_t_len;
    upd = incr_ret->updates.kdb_ulog_t_val;
    fupd = upd;

    /*
     * We reset last_sno and last_time to 0, if krb5_db2_db_put_principal
     * or krb5_db2_db_delete_principal fail.
     */
    errlast.last_sno = (unsigned int)0;
    errlast.last_time.seconds = (unsigned int)0;
    errlast.last_time.useconds = (unsigned int)0;

    if ((retval = krb5_db_open(context, db_args,
                               KRB5_KDB_OPEN_RW|KRB5_KDB_SRV_TYPE_ADMIN)))
        goto cleanup;

    for (i = 0; i < no_of_updates; i++) {
        if (!upd->kdb_commit)
            continue;

        if (upd->kdb_deleted) {
            dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len
                                 + 1) * sizeof (char));

            if (dbprincstr == NULL) {
                retval = ENOMEM;
                goto cleanup;
            }

            (void) strncpy(dbprincstr,
                           (char *)upd->kdb_princ_name.utf8str_t_val,
                           (upd->kdb_princ_name.utf8str_t_len + 1));
            dbprincstr[upd->kdb_princ_name.utf8str_t_len] = 0;

            if ((retval = krb5_parse_name(context, dbprincstr,
                                          &dbprinc))) {
                goto cleanup;
            }

            free(dbprincstr);

            retval = krb5int_delete_principal_no_log(context, dbprinc);

            if (dbprinc) {
                krb5_free_principal(context, dbprinc);
                dbprinc = NULL;
            }

            if (retval)
                goto cleanup;
        } else {
            entry = (krb5_db_entry *)malloc(sizeof (krb5_db_entry));

            if (!entry) {
                retval = errno;
                goto cleanup;
            }

            (void) memset(entry, 0, sizeof (krb5_db_entry));

            if ((retval = ulog_conv_2dbentry(context, &entry, upd)))
                goto cleanup;

            retval = krb5int_put_principal_no_log(context, entry);

            if (entry) {
                krb5_db_free_principal(context, entry);
                entry = NULL;
            }
            if (retval)
                goto cleanup;
        }

        upd++;
    }

cleanup:
    if (fupd)
        ulog_free_entries(fupd, no_of_updates);

    if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
        if (retval)
            ulog_finish_update_slave(ulog, errlast);
        else
            ulog_finish_update_slave(ulog, incr_ret->lastentry);
    }

    return (retval);
}