示例#1
0
static krb5_error_code
receive_everything(krb5_context context, int fd,
		   kadm5_server_context *server_context,
		   krb5_auth_context auth_context)
{
    int ret;
    krb5_data data;
    uint32_t vno = 0;
    uint32_t opcode;
    krb5_storage *sp;

    char *dbname;
    HDB *mydb;

    krb5_warnx(context, "receive complete database");

    ret = asprintf(&dbname, "%s-NEW", server_context->db->hdb_name);
    if (ret == -1)
        krb5_err(context, IPROPD_RESTART, ENOMEM, "asprintf");
    ret = hdb_create(context, &mydb, dbname);
    if(ret)
        krb5_err(context, IPROPD_RESTART, ret, "hdb_create");
    free(dbname);

    ret = hdb_set_master_keyfile(context,
				 mydb, server_context->config.stash_file);
    if(ret)
        krb5_err(context, IPROPD_RESTART, ret, "hdb_set_master_keyfile");

    /* I really want to use O_EXCL here, but given that I can't easily clean
       up on error, I won't */
    ret = mydb->hdb_open(context, mydb, O_RDWR | O_CREAT | O_TRUNC, 0600);
    if (ret)
        krb5_err(context, IPROPD_RESTART, ret, "db->open");

    (void) mydb->hdb_set_sync(context, mydb, 0);

    sp = NULL;
    krb5_data_zero(&data);
    do {
	ret = krb5_read_priv_message(context, auth_context, &fd, &data);

	if (ret) {
	    krb5_warn(context, ret, "krb5_read_priv_message");
	    goto cleanup;
	}

	sp = krb5_storage_from_data(&data);
	if (sp == NULL)
	    krb5_errx(context, IPROPD_RESTART, "krb5_storage_from_data");
	krb5_ret_uint32(sp, &opcode);
	if (opcode == ONE_PRINC) {
	    krb5_data fake_data;
	    hdb_entry_ex entry;

	    krb5_storage_free(sp);

	    fake_data.data   = (char *)data.data + 4;
	    fake_data.length = data.length - 4;

	    memset(&entry, 0, sizeof(entry));

	    ret = hdb_value2entry(context, &fake_data, &entry.entry);
	    if (ret)
		krb5_err(context, IPROPD_RESTART, ret, "hdb_value2entry");
	    ret = mydb->hdb_store(server_context->context,
				  mydb,
				  0, &entry);
	    if (ret)
		krb5_err(context, IPROPD_RESTART_SLOW, ret, "hdb_store");

	    hdb_free_entry(context, &entry);
	    krb5_data_free(&data);
	} else if (opcode == NOW_YOU_HAVE)
	    ;
	else
	    krb5_errx(context, 1, "strange opcode %d", opcode);
    } while (opcode == ONE_PRINC);

    if (opcode != NOW_YOU_HAVE)
        krb5_errx(context, IPROPD_RESTART_SLOW,
                  "receive_everything: strange %d", opcode);

    krb5_ret_uint32(sp, &vno);
    krb5_storage_free(sp);

    reinit_log(context, server_context, vno);

    ret = mydb->hdb_set_sync(context, mydb, 1);
    if (ret)
        krb5_err(context, IPROPD_RESTART_SLOW, ret, "failed to sync the received HDB");
    ret = mydb->hdb_close(context, mydb);
    if (ret)
        krb5_err(context, IPROPD_RESTART_SLOW, ret, "db->close");

    ret = mydb->hdb_rename(context, mydb, server_context->db->hdb_name);
    if (ret)
        krb5_err(context, IPROPD_RESTART_SLOW, ret, "db->rename");


    return 0;

 cleanup:
    krb5_data_free(&data);

    if (ret)
        krb5_err(context, IPROPD_RESTART_SLOW, ret, "db->close");

    ret = mydb->hdb_destroy(context, mydb);
    if (ret)
        krb5_err(context, IPROPD_RESTART, ret, "db->destroy");

    krb5_warnx(context, "receive complete database, version %ld", (long)vno);
    return ret;
}