#include <kim/kim.h>
#include <kim/kim_ui_plugin.h>
#include <asl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
const char *magic;
aslclient asl_context;
int got_error;
} *test_ui_context;
const char *magic = "test_ui_context_magic";
static void test_ui_vlog (test_ui_context in_context,
const char *in_format,
va_list in_args)
{
if (!in_context) {
asl_log (NULL, NULL, ASL_LEVEL_ERR, "NULL context!");
} else if (strcmp (in_context->magic, magic)) {
asl_log (NULL, NULL, ASL_LEVEL_ERR,
"Magic mismatch. Context corrupted!");
} else {
asl_vlog (in_context->asl_context, NULL, ASL_LEVEL_NOTICE,
in_format, in_args);
}
}
static void test_ui_log_ (void *in_context,
const char *in_function,
const char *in_format, ...)
{
test_ui_context context = in_context;
char *format = NULL;
va_list args;
asprintf (&format, "%s: %s", in_function, in_format);
va_start (args, in_format);
test_ui_vlog (context, format, args);
va_end (args);
free (format);
}
#define test_ui_log(context, format, ...) test_ui_log_(context, __FUNCTION__, format, ## __VA_ARGS__)
#pragma mark -
static kim_error test_ui_init (void **out_context)
{
kim_error err = KIM_NO_ERROR;
test_ui_context context = NULL;
if (!err) {
context = malloc (sizeof (*context));
if (!context) { err = KIM_OUT_OF_MEMORY_ERR; }
}
if (!err) {
context->got_error = 0;
context->magic = magic;
context->asl_context = asl_open (NULL,
"com.apple.console",
ASL_OPT_NO_DELAY | ASL_OPT_STDERR);
if (!context->asl_context) { err = KIM_OUT_OF_MEMORY_ERR; }
}
if (!err) {
test_ui_log (context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (NULL, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
if (!err) {
*out_context = context;
context = NULL;
}
free (context);
return err;
}
static kim_error test_ui_enter_identity (void *in_context,
kim_options io_options,
kim_identity *out_identity,
kim_boolean *out_change_password)
{
kim_error err = KIM_NO_ERROR;
kim_identity identity = NULL;
test_ui_log (in_context, "entering...");
if (!err) {
test_ui_context context = in_context;
if (context->got_error > 1) {
test_ui_log (in_context, "\tfailed twice, giving up...");
context->got_error = 0;
err = KIM_USER_CANCELED_ERR;
}
}
if (!err) {
err = kim_options_set_lifetime (io_options, 1800);
}
if (!err) {
err = kim_options_set_renewal_lifetime (io_options, 3600);
}
if (!err) {
err = kim_identity_create_from_string (&identity,
"nobody@TEST-KERBEROS-1.5");
}
if (!err) {
*out_identity = identity;
identity = NULL;
*out_change_password = 0;
}
kim_identity_free (&identity);
if (!err) {
test_ui_log (in_context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (in_context, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
return err;
}
static kim_error test_ui_select_identity (void *in_context,
kim_selection_hints io_hints,
kim_identity *out_identity,
kim_boolean *out_change_password)
{
kim_error err = KIM_NO_ERROR;
kim_identity identity = NULL;
kim_options options = NULL;
test_ui_log (in_context, "entering...");
if (!err) {
test_ui_context context = in_context;
if (context->got_error > 1) {
test_ui_log (in_context, "\tfailed twice, giving up...");
context->got_error = 0;
err = KIM_USER_CANCELED_ERR;
}
}
if (!err) {
err = kim_selection_hints_get_options (io_hints, &options);
}
if (!err && !options) {
err = kim_options_create (&options);
}
if (!err) {
err = kim_options_set_lifetime (options, 1800);
}
if (!err) {
err = kim_options_set_renewal_lifetime (options, 3600);
}
if (!err) {
err = kim_selection_hints_set_options (io_hints, options);
}
if (!err) {
err = kim_identity_create_from_string (&identity,
"nobody@TEST-KERBEROS-1.5");
}
if (!err) {
*out_identity = identity;
identity = NULL;
*out_change_password = 0;
}
kim_options_free (&options);
kim_identity_free (&identity);
if (!err) {
test_ui_log (in_context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (in_context, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
return err;
}
static kim_error test_ui_auth_prompt (void *in_context,
kim_identity in_identity,
kim_prompt_type in_type,
kim_boolean in_allow_save_reply,
kim_boolean in_hide_reply,
kim_string in_title,
kim_string in_message,
kim_string in_description,
char **out_reply,
kim_boolean *out_save_reply)
{
kim_error err = KIM_NO_ERROR;
kim_string string = NULL;
char *reply = NULL;
test_ui_log (in_context, "entering...");
if (!err) {
err = kim_identity_get_display_string (in_identity, &string);
}
if (!err) {
test_ui_log (in_context, "\tidentity = %s", string);
test_ui_log (in_context, "\ttype = %d", in_type);
test_ui_log (in_context, "\tallow_save_reply = %d", in_allow_save_reply);
test_ui_log (in_context, "\thide_reply = %d", in_hide_reply);
test_ui_log (in_context, "\ttitle = %s", in_title);
test_ui_log (in_context, "\tmessage = %s", in_message);
test_ui_log (in_context, "\tdescription = %s", in_description);
reply = strdup ("ydobon");
if (!reply) { err = KIM_OUT_OF_MEMORY_ERR; }
}
if (!err) {
test_ui_context context = in_context;
if (context->got_error > 1) {
test_ui_log (in_context, "\tfailed twice, giving up...");
context->got_error = 0;
err = KIM_USER_CANCELED_ERR;
}
}
if (!err) {
*out_reply = reply;
reply = NULL;
*out_save_reply = 0;
}
free (reply);
kim_string_free (&string);
if (!err) {
test_ui_log (in_context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (in_context, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
return err;
}
static kim_error test_ui_change_password (void *in_context,
kim_identity in_identity,
kim_boolean in_old_password_expired,
char **out_old_password,
char **out_new_password,
char **out_verify_password)
{
kim_error err = KIM_NO_ERROR;
kim_string string = NULL;
char *old_password = NULL;
char *new_password = NULL;
char *vfy_password = NULL;
test_ui_log (in_context, "entering...");
if (!err) {
err = kim_identity_get_display_string (in_identity, &string);
}
if (!err) {
test_ui_log (in_context, "\tidentity = %s", string);
test_ui_log (in_context, "\told_password_expired = %d",
in_old_password_expired);
old_password = strdup ("ydobon");
new_password = strdup ("foo");
vfy_password = strdup ("foo");
if (!old_password || !new_password || !vfy_password) {
err = KIM_OUT_OF_MEMORY_ERR;
}
}
if (!err) {
test_ui_context context = in_context;
if (context->got_error > 1) {
test_ui_log (in_context, "\tfailed twice, giving up...");
context->got_error = 0;
err = KIM_USER_CANCELED_ERR;
}
}
if (!err) {
*out_old_password = old_password;
old_password = NULL;
*out_new_password = new_password;
new_password = NULL;
*out_verify_password = vfy_password;
vfy_password = NULL;
}
free (old_password);
free (new_password);
free (vfy_password);
kim_string_free (&string);
if (!err) {
test_ui_log (in_context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (in_context, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
return err;
}
static kim_error test_ui_handle_error (void *in_context,
kim_identity in_identity,
kim_error in_error,
kim_string in_error_message,
kim_string in_error_description)
{
kim_error err = KIM_NO_ERROR;
kim_string string = NULL;
test_ui_log (in_context, "entering...");
if (!err) {
err = kim_identity_get_display_string (in_identity, &string);
}
if (!err) {
test_ui_context context = in_context;
test_ui_log (in_context, "\tidentity = %s", string);
test_ui_log (in_context, "\terror = %d", in_error);
test_ui_log (in_context, "\tmessage = %s", in_error_message);
test_ui_log (in_context, "\tdescription = %s", in_error_description);
context->got_error++;
}
kim_string_free (&string);
if (!err) {
test_ui_log (in_context, "returning with no error.");
} else {
kim_string estring = NULL;
kim_string_create_for_last_error (&estring, err);
test_ui_log (in_context, "returning %d: %s", err, estring);
kim_string_free (&estring);
}
return err;
}
static void test_ui_free_string (void *in_context,
char **io_string)
{
test_ui_log (in_context, "freeing string %p", *io_string);
free (*io_string);
*io_string = NULL;
}
static kim_error test_ui_fini (void *io_context)
{
kim_error err = KIM_NO_ERROR;
test_ui_log (io_context, "deallocating...");
if (io_context) {
test_ui_context context = io_context;
asl_close (context->asl_context);
free (context);
}
return err;
}
kim_ui_plugin_ftable_v0 kim_ui_0 = {
0,
test_ui_init,
test_ui_enter_identity,
test_ui_select_identity,
test_ui_auth_prompt,
test_ui_change_password,
test_ui_handle_error,
test_ui_free_string,
test_ui_fini
};