g_main_loop_quit(main_loop);
}
-enum wispr_pages {
- WISPR_PAGE_NONE,
- WISPR_PAGE_REDIRECT,
- WISPR_PAGE_PROXY,
- WISPR_PAGE_AUTHENTICATION_REPLY,
- WISPR_PAGE_AUTHENTICATION_POLL_REPLY,
- WISPR_PAGE_LOGOFF_REPLY,
- WISPR_PAGE_ABORT_LOGIN_REPLY,
+static const char *message_type_to_string(int message_type)
+{
+ switch (message_type) {
+ case 100:
+ return "Initial redirect message";
+ case 110:
+ return "Proxy notification";
+ case 120:
+ return "Authentication notification";
+ case 130:
+ return "Logoff notification";
+ case 140:
+ return "Response to Authentication Poll";
+ case 150:
+ return "Response to Abort Login";
+ }
+
+ return NULL;
+}
+
+static const char *response_code_to_string(int response_code)
+{
+ switch (response_code) {
+ case 0:
+ return "No error";
+ case 50:
+ return "Login succeeded";
+ case 100:
+ return "Login failed";
+ case 102:
+ return "RADIUS server error/timeout";
+ case 105:
+ return "RADIUS server not enabled";
+ case 150:
+ return "Logoff succeeded";
+ case 151:
+ return "Login aborted";
+ case 200:
+ return "Proxy detection/repeat operation";
+ case 201:
+ return "Authentication pending";
+ case 255:
+ return "Access gateway internal error";
+ }
+
+ return NULL;
+}
+
+struct wispr_msg {
+ gboolean has_error;
+ const char *current_element;
+ int message_type;
+ int response_code;
+ char *login_url;
+ char *logoff_url;
};
-enum wispr_elements {
- WISPR_NONE,
- WISPR_ACCESS_PROCEDURE,
- WISPR_ACCESS_LOCATION,
- WISPR_LOCATION_NAME,
- WISPR_LOGIN_URL,
- WISPR_ABORT_LOGIN_URL,
- WISPR_MESSAGE_TYPE,
- WISPR_RESPONSE_CODE,
- WISPR_NEXT_URL,
- WISPR_DELAY,
- WISPR_REPLY_MESSAGE,
- WISPR_LOGIN_RESULTS_URL,
- WISPR_LOGOFF_URL,
+static inline void wispr_msg_init(struct wispr_msg *msg)
+{
+ msg->has_error = FALSE;
+ msg->current_element = NULL;
+
+ msg->message_type = -1;
+ msg->response_code = -1;
+
+ g_free(msg->login_url);
+ msg->login_url = NULL;
+
+ g_free(msg->logoff_url);
+ msg->logoff_url = NULL;
+}
+
+struct wispr_session {
+ GWeb *web;
+ GWebParser *parser;
+ guint request;
+ struct wispr_msg msg;
+ const char *username;
+ const char *password;
+ const char *originurl;
+ char *formdata;
};
-static enum wispr_pages current_page = WISPR_NONE;
-static enum wispr_elements current_element = WISPR_NONE;
+static struct {
+ const char *str;
+ enum {
+ WISPR_ELEMENT_NONE,
+ WISPR_ELEMENT_ACCESS_PROCEDURE,
+ WISPR_ELEMENT_ACCESS_LOCATION,
+ WISPR_ELEMENT_LOCATION_NAME,
+ WISPR_ELEMENT_LOGIN_URL,
+ WISPR_ELEMENT_ABORT_LOGIN_URL,
+ WISPR_ELEMENT_MESSAGE_TYPE,
+ WISPR_ELEMENT_RESPONSE_CODE,
+ WISPR_ELEMENT_NEXT_URL,
+ WISPR_ELEMENT_DELAY,
+ WISPR_ELEMENT_REPLY_MESSAGE,
+ WISPR_ELEMENT_LOGIN_RESULTS_URL,
+ WISPR_ELEMENT_LOGOFF_URL,
+ } element;
+} wispr_element_map[] = {
+ { "AccessProcedure", WISPR_ELEMENT_ACCESS_PROCEDURE },
+ { "AccessLocation", WISPR_ELEMENT_ACCESS_LOCATION },
+ { "LocationName", WISPR_ELEMENT_LOCATION_NAME },
+ { "LoginURL", WISPR_ELEMENT_LOGIN_URL },
+ { "AbortLoginURL", WISPR_ELEMENT_ABORT_LOGIN_URL },
+ { "MessageType", WISPR_ELEMENT_MESSAGE_TYPE },
+ { "ResponseCode", WISPR_ELEMENT_RESPONSE_CODE },
+ { "NextURL", WISPR_ELEMENT_NEXT_URL },
+ { "Delay", WISPR_ELEMENT_DELAY },
+ { "ReplyMessage", WISPR_ELEMENT_REPLY_MESSAGE },
+ { "LoginResultsURL", WISPR_ELEMENT_LOGIN_RESULTS_URL },
+ { "LogoffURL", WISPR_ELEMENT_LOGOFF_URL },
+ { NULL, WISPR_ELEMENT_NONE },
+};
static void start_element_handler(GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_values,
gpointer user_data, GError **error)
{
- if (g_str_equal(element_name, "Redirect") == TRUE)
- current_page = WISPR_PAGE_REDIRECT;
- else if (g_str_equal(element_name, "Proxy") == TRUE)
- current_page = WISPR_PAGE_PROXY;
- else if (g_str_equal(element_name, "AuthenticationReply") == TRUE)
- current_page = WISPR_PAGE_AUTHENTICATION_REPLY;
- else if (g_str_equal(element_name, "AuthenticationPollReply") == TRUE)
- current_page = WISPR_PAGE_AUTHENTICATION_POLL_REPLY;
- else if (g_str_equal(element_name, "LogoffReply") == TRUE)
- current_page = WISPR_PAGE_LOGOFF_REPLY;
- else if (g_str_equal(element_name, "AbortLoginReply") == TRUE)
- current_page = WISPR_PAGE_ABORT_LOGIN_REPLY;
- else
- current_page = WISPR_PAGE_NONE;
-
- if (g_str_equal(element_name, "AccessProcedure") == TRUE)
- current_element = WISPR_ACCESS_PROCEDURE;
- else if (g_str_equal(element_name, "AccessLocation") == TRUE)
- current_element = WISPR_ACCESS_LOCATION;
- else if (g_str_equal(element_name, "LocationName") == TRUE)
- current_element = WISPR_LOCATION_NAME;
- else if (g_str_equal(element_name, "LoginURL") == TRUE)
- current_element = WISPR_LOGIN_URL;
- else if (g_str_equal(element_name, "AbortLoginURL") == TRUE)
- current_element = WISPR_ABORT_LOGIN_URL;
- else if (g_str_equal(element_name, "MessageType") == TRUE)
- current_element = WISPR_MESSAGE_TYPE;
- else if (g_str_equal(element_name, "ResponseCode") == TRUE)
- current_element = WISPR_RESPONSE_CODE;
- else if (g_str_equal(element_name, "NextURL") == TRUE)
- current_element = WISPR_NEXT_URL;
- else if (g_str_equal(element_name, "Delay") == TRUE)
- current_element = WISPR_DELAY;
- else if (g_str_equal(element_name, "ReplyMessage") == TRUE)
- current_element = WISPR_REPLY_MESSAGE;
- else if (g_str_equal(element_name, "LoginResultsURL") == TRUE)
- current_element = WISPR_LOGIN_RESULTS_URL;
- else if (g_str_equal(element_name, "LogoffURL") == TRUE)
- current_element = WISPR_LOGOFF_URL;
- else
- current_element = WISPR_NONE;
+ struct wispr_msg *msg = user_data;
+
+ msg->current_element = element_name;
}
static void end_element_handler(GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data, GError **error)
{
- current_page = WISPR_PAGE_NONE;
+ struct wispr_msg *msg = user_data;
- current_element = WISPR_NONE;
+ msg->current_element = NULL;
}
static void text_handler(GMarkupParseContext *context,
const gchar *text, gsize text_len,
gpointer user_data, GError **error)
{
- int value;
-
- switch (current_page) {
- case WISPR_PAGE_NONE:
- break;
- case WISPR_PAGE_REDIRECT:
- printf("[ Redirect ]\n");
- break;
- case WISPR_PAGE_PROXY:
- printf("[ Proxy ]\n");
- break;
- case WISPR_PAGE_AUTHENTICATION_REPLY:
- printf("[ Authentication reply ]\n");
- break;
- case WISPR_PAGE_AUTHENTICATION_POLL_REPLY:
- printf("[ Authentication poll reply ]\n");
- break;
- case WISPR_PAGE_LOGOFF_REPLY:
- printf("[ Logoff reply ]\n");
- break;
- case WISPR_PAGE_ABORT_LOGIN_REPLY:
- printf("[ Abort login reply ]\n");
- break;
- }
-
- switch (current_element) {
- case WISPR_NONE:
- break;
- case WISPR_ACCESS_PROCEDURE:
- printf("Access procedure: %s\n", text);
- break;
- case WISPR_ACCESS_LOCATION:
- printf("Access location: %s\n", text);
- break;
- case WISPR_LOCATION_NAME:
- printf("Location name: %s\n", text);
- break;
- case WISPR_LOGIN_URL:
- printf("Login URL: %s\n", text);
- break;
- case WISPR_ABORT_LOGIN_URL:
- printf("Abort login URL: %s\n", text);
- break;
- case WISPR_MESSAGE_TYPE:
- value = atoi(text);
- printf("Message type: %d\n", value);
- switch (value) {
- case 100:
- printf(" Initial redirect message\n");
- break;
- case 110:
- printf(" Proxy notification\n");
- break;
- case 120:
- printf(" Authentication notification\n");
- break;
- case 130:
- printf(" Logoff notification\n");
- break;
- case 140:
- printf(" Response to Authentication Poll\n");
- break;
- case 150:
- printf(" Response to Abort Login\n");
- break;
- }
- break;
- case WISPR_RESPONSE_CODE:
- value = atoi(text);
- printf("Response code: %d\n", value);
- switch (value) {
- case 0:
- printf(" No error\n");
- break;
- case 50:
- printf(" Login succeeded (Access ACCEPT)\n");
- break;
- case 100:
- printf(" Login failed (Access REJECT)\n");
+ struct wispr_msg *msg = user_data;
+ int i;
+
+ if (msg->current_element == NULL)
+ return;
+
+ for (i = 0; wispr_element_map[i].str; i++) {
+ if (g_str_equal(wispr_element_map[i].str,
+ msg->current_element) == FALSE)
+ continue;
+
+ switch (wispr_element_map[i].element) {
+ case WISPR_ELEMENT_NONE:
+ case WISPR_ELEMENT_ACCESS_PROCEDURE:
+ case WISPR_ELEMENT_ACCESS_LOCATION:
+ case WISPR_ELEMENT_LOCATION_NAME:
break;
- case 102:
- printf(" RADIUS server error/timeout\n");
+ case WISPR_ELEMENT_LOGIN_URL:
+ g_free(msg->login_url);
+ msg->login_url = g_strdup(text);
break;
- case 105:
- printf(" RADIUS server not enabled\n");
+ case WISPR_ELEMENT_ABORT_LOGIN_URL:
break;
- case 150:
- printf(" Logoff succeeded\n");
+ case WISPR_ELEMENT_MESSAGE_TYPE:
+ msg->message_type = atoi(text);
break;
- case 151:
- printf(" Login aborted\n");
+ case WISPR_ELEMENT_RESPONSE_CODE:
+ msg->response_code = atoi(text);
break;
- case 200:
- printf(" Proxy detection/repeat operation\n");
- break;
- case 201:
- printf(" Authentication pending\n");
- break;
- case 255:
- printf(" Access gateway internal error\n");
+ case WISPR_ELEMENT_NEXT_URL:
+ case WISPR_ELEMENT_DELAY:
+ case WISPR_ELEMENT_REPLY_MESSAGE:
+ case WISPR_ELEMENT_LOGIN_RESULTS_URL:
+ case WISPR_ELEMENT_LOGOFF_URL:
break;
}
- break;
- case WISPR_NEXT_URL:
- printf("Next URL: %s\n", text);
- break;
- case WISPR_DELAY:
- value = atoi(text);
- printf("Delay: %d seconds\n", value);
- break;
- case WISPR_REPLY_MESSAGE:
- printf("Reply message: %s\n", text);
- break;
- case WISPR_LOGIN_RESULTS_URL:
- printf("Login results URL: %s\n", text);
- break;
- case WISPR_LOGOFF_URL:
- printf("Logoff URL: %s\n", text);
- break;
}
}
static void error_handler(GMarkupParseContext *context,
GError *error, gpointer user_data)
{
- printf("%s\n", error->message);
+ struct wispr_msg *msg = user_data;
+
+ msg->has_error = TRUE;
}
static const GMarkupParser wispr_parser = {
static void parser_callback(const char *str, gpointer user_data)
{
+ struct wispr_session *wispr = user_data;
GMarkupParseContext *context;
gboolean result;
//printf("%s\n", str);
context = g_markup_parse_context_new(&wispr_parser,
- G_MARKUP_TREAT_CDATA_AS_TEXT, NULL, NULL);
+ G_MARKUP_TREAT_CDATA_AS_TEXT, &wispr->msg, NULL);
result = g_markup_parse_context_parse(context, str, strlen(str), NULL);
-
- result = g_markup_parse_context_end_parse(context, NULL);
+ if (result == TRUE)
+ result = g_markup_parse_context_end_parse(context, NULL);
g_markup_parse_context_free(context);
}
-static guint request_id;
-static GWebParser *request_parser;
+static gboolean wispr_input(const guint8 **data, gsize *length,
+ gpointer user_data)
+{
+ struct wispr_session *wispr = user_data;
+
+ g_free(wispr->formdata);
+ wispr->formdata = g_strdup_printf("button=Login&UserName=%s&"
+ "Password=%s&FNAME=0&OriginatingServer=%s",
+ wispr->username, wispr->password, wispr->originurl);
-static gboolean web_result(GWebResult *result, gpointer user_data)
+ *data = (guint8 *) wispr->formdata;
+ *length = strlen(wispr->formdata);
+
+ return FALSE;
+}
+
+static gboolean wispr_result(GWebResult *result, gpointer user_data)
{
+ struct wispr_session *wispr = user_data;
const guint8 *chunk;
gsize length;
guint16 status;
gdouble elapsed;
- status = g_web_result_get_status(result);
- if (status == 200)
- goto done;
-
g_web_result_get_chunk(result, &chunk, &length);
if (length > 0) {
//printf("%s\n", (char *) chunk);
- g_web_parser_feed_data(request_parser, chunk, length);
+ g_web_parser_feed_data(wispr->parser, chunk, length);
return TRUE;
}
- g_web_parser_end_data(request_parser);
+ g_web_parser_end_data(wispr->parser);
+
+ status = g_web_result_get_status(result);
-done:
g_print("status: %03u\n", status);
elapsed = g_timer_elapsed(timer, NULL);
g_print("elapse: %f seconds\n", elapsed);
+ if (wispr->msg.message_type < 0)
+ goto done;
+
+ printf("Message type: %s (%d)\n",
+ message_type_to_string(wispr->msg.message_type),
+ wispr->msg.message_type);
+ printf("Response code: %s (%d)\n",
+ response_code_to_string(wispr->msg.response_code),
+ wispr->msg.response_code);
+ if (wispr->msg.login_url != NULL)
+ printf("Login URL: %s\n", wispr->msg.login_url);
+ if (wispr->msg.logoff_url != NULL)
+ printf("Logoff URL: %s\n", wispr->msg.logoff_url);
+ printf("\n");
+
+ if (status == 302 && wispr->msg.message_type == 100) {
+ wispr->request = g_web_request_post(wispr->web,
+ wispr->msg.login_url,
+ "application/x-www-form-urlencoded",
+ wispr_input, wispr_result, wispr);
+
+ wispr_msg_init(&wispr->msg);
+
+ return FALSE;
+ } else if (status == 200 && wispr->msg.message_type == 120) {
+ int code = wispr->msg.response_code;
+ printf("Login process: %s\n",
+ code == 50 ? "SUCCESS" : "FAILURE");
+ }
+
+done:
g_main_loop_quit(main_loop);
return FALSE;
static gboolean option_debug = FALSE;
static gchar *option_nameserver = NULL;
+static gchar *option_username = NULL;
+static gchar *option_password = NULL;
static gchar *option_url = NULL;
static GOptionEntry options[] = {
"Enable debug output" },
{ "nameserver", 'n', 0, G_OPTION_ARG_STRING, &option_nameserver,
"Specify nameserver", "ADDRESS" },
- { "url", 'u', 0, G_OPTION_ARG_STRING, &option_url,
+ { "username", 'u', 0, G_OPTION_ARG_STRING, &option_username,
+ "Specify username", "USERNAME" },
+ { "password", 'p', 0, G_OPTION_ARG_STRING, &option_password,
+ "Specify password", "PASSWORD" },
+ { "url", 'U', 0, G_OPTION_ARG_STRING, &option_url,
"Specify arbitrary request", "URL" },
{ NULL },
};
GOptionContext *context;
GError *error = NULL;
struct sigaction sa;
- GWeb *web;
+ struct wispr_session wispr;
int index = 0;
context = g_option_context_new(NULL);
g_option_context_free(context);
- web = g_web_new(index);
- if (web == NULL) {
+ memset(&wispr, 0, sizeof(wispr));
+ wispr_msg_init(&wispr.msg);
+
+ wispr.web = g_web_new(index);
+ if (wispr.web == NULL) {
fprintf(stderr, "Failed to create web service\n");
return 1;
}
if (option_debug == TRUE)
- g_web_set_debug(web, web_debug, "WEB");
+ g_web_set_debug(wispr.web, web_debug, "WEB");
main_loop = g_main_loop_new(NULL, FALSE);
if (option_nameserver != NULL) {
- g_web_add_nameserver(web, option_nameserver);
+ g_web_add_nameserver(wispr.web, option_nameserver);
g_free(option_nameserver);
}
- g_web_set_accept(web, NULL);
- g_web_set_user_agent(web, "SmartClient/%s wispr", VERSION);
- g_web_set_close_connection(web, TRUE);
+ g_web_set_accept(wispr.web, NULL);
+ g_web_set_user_agent(wispr.web, "SmartClient/%s wispr", VERSION);
+ g_web_set_close_connection(wispr.web, TRUE);
if (option_url == NULL)
option_url = g_strdup(DEFAULT_URL);
+ wispr.username = option_username;
+ wispr.password = option_password;
+ wispr.originurl = option_url;
+
timer = g_timer_new();
- request_parser = g_web_parser_new("<WISPAccessGatewayParam",
+ wispr.parser = g_web_parser_new("<WISPAccessGatewayParam",
"WISPAccessGatewayParam>",
- parser_callback, NULL);
-
- g_web_parser_ref(request_parser);
- g_web_parser_unref(request_parser);
+ parser_callback, &wispr);
- request_id = g_web_request_get(web, option_url, web_result, NULL);
-
- g_free(option_url);
+ wispr.request = g_web_request_get(wispr.web, option_url,
+ wispr_result, &wispr);
- if (request_id == 0) {
+ if (wispr.request == 0) {
fprintf(stderr, "Failed to start request\n");
return 1;
}
g_timer_destroy(timer);
- g_web_unref(web);
+ if (wispr.request > 0)
+ g_web_cancel_request(wispr.web, wispr.request);
+
+ g_web_parser_unref(wispr.parser);
+ g_web_unref(wispr.web);
g_main_loop_unref(main_loop);
+ g_free(option_username);
+ g_free(option_password);
+ g_free(option_url);
+
return 0;
}