Initial commit

This commit is contained in:
oupson 2021-10-25 09:39:30 +02:00
commit eb2ee9e570
9 changed files with 486 additions and 0 deletions

1
.clang-format Normal file
View File

@ -0,0 +1 @@
IndentWidth: 4

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
compile_commands.json
.cache
.vscode
bin
lib
obj

39
Makefile Normal file
View File

@ -0,0 +1,39 @@
.PHONY: all clean format
all: lib/libauthunivorleans.so lib/libauthunivorleans.a bin/test
OPTIMISATION ?= 0
CFLAGS = -Iinclude $(DEFINES) `pkg-config --cflags libcurl` -fPIC -Wall -Werror
FLAGS = -g
SRCS=$(wildcard src/*.c)
OBJS=$(SRCS:src/%.c=obj/%.o)
DEPS = $(OBJS:%.o=%.d)
-include $(DEPS)
clean:
rm -fr bin/* obj/* lib/*
format:
clang-format src/*.c -i
clang-format include/*.h -i
CC ?= $(CC)
obj/%.o: src/%.c
@mkdir -p $(@D)
$(CC) -c -O$(OPTIMISATION) -MMD -g -o $@ $< $(CFLAGS) $(FLAGS)
lib/libauthunivorleans.so: obj/auth_univ_orleans.o obj/cookie_iterator.o
@mkdir -p $(@D)
$(CC) -fpic -shared -O$(OPTIMISATION) $(FLAGS) -flto -o $@ $^ `pkg-config --libs libcurl` `pkg-config --libs tidy`
lib/libauthunivorleans.a: obj/auth_univ_orleans.o obj/cookie_iterator.o
@mkdir -p $(@D)
$(AR) -cr $@ $^
bin/test: obj/test.o lib/libauthunivorleans.a
@mkdir -p $(@D)
$(CC) -g -O$(OPTIMISATION) -flto -o $@ $^ `pkg-config --libs libcurl` `pkg-config --libs tidy`

1
README.md Normal file
View File

@ -0,0 +1 @@
# Auth Univ Orléans

View File

@ -0,0 +1,9 @@
#ifndef AUTH_UNIV_ORLEANS
#define AUTH_UNIV_ORLEANS
#include <cookie_iterator.h>
#include <curl/curl.h>
cookie_iterator_t *auth_univ_get_session_token(char *username, char *password);
int auth_univ_orleans_login(CURL *handle, char *username, char *password);
#endif

39
include/cookie_iterator.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef COOKIE_ITERATOR_H
#define COOKIE_ITERATOR_H
#include <curl/curl.h>
#include <stdbool.h>
struct cookie_iterator {
struct curl_slist *cookie_list;
struct curl_slist *current;
struct cookie *cookie;
};
struct cookie {
char hostname[256];
bool include_subdomains;
char path[256];
bool secure;
long expire;
char name[256];
char value[256];
};
typedef struct cookie_iterator cookie_iterator_t;
typedef struct cookie cookie_t;
cookie_iterator_t *new_cookie_iterator_from_curl(CURL *handle);
cookie_t *cookie_iterator_next(cookie_iterator_t *iterator);
void cookie_iterator_free(cookie_iterator_t *iterator);
char *cookie_hostname(cookie_t *cookie);
bool cookie_include_subdomains(cookie_t *cookie);
char *cookie_path(cookie_t *cookie);
bool cookie_secure(cookie_t *cookie);
int cookie_expire(cookie_t *cookie);
char *cookie_name(cookie_t *cookie);
char *cookie_value(cookie_t *cookie);
void cookie_free(cookie_t *cookie);
#endif

212
src/auth_univ_orleans.c Normal file
View File

@ -0,0 +1,212 @@
#include <auth_univ_orleans.h>
#include <cookie_iterator.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include <tidy/tidy.h>
#include <tidy/tidybuffio.h>
int private_auth_univ_orleans_post_login(CURL *handle, char *lt, char *action,
char *username, char *password);
int private_auth_univ_orleans_get_action_and_lt(CURL *handle, char **lt,
char **action);
size_t private_auth_univ_orleans_dumb_write_callback(void *data, size_t size,
size_t nmemb,
void *userp) {
return size * nmemb;
}
uint private_auth_univ_orleans_tidy_buf_write_cb(char *in, uint size,
uint nmemb, TidyBuffer *out) {
uint r;
r = size * nmemb;
tidyBufAppend(out, in, r);
return r;
}
int private_auth_univ_orleans_get_action_and_lt_from_node(TidyDoc doc,
TidyNode tnod,
char **lt,
char **action);
cookie_iterator_t *auth_univ_get_session_token(char *username, char *password) {
CURL *handle = curl_easy_init();
char errbuf[CURL_ERROR_SIZE];
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf);
/* set the error buffer as empty before performing a request */
errbuf[0] = 0;
// curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 1L);
auth_univ_orleans_login(handle, username, password);
cookie_iterator_t *list = new_cookie_iterator_from_curl(handle);
curl_easy_cleanup(handle);
return list;
}
int auth_univ_orleans_login(CURL *handle, char *username, char *password) {
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(handle, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(handle, CURLOPT_USERAGENT,
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:93.0) "
"Gecko/20100101 Firefox/93.0");
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION,
private_auth_univ_orleans_dumb_write_callback);
curl_easy_setopt(handle, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(handle, CURLOPT_URL, "https://ent.univ-orleans.fr/");
curl_easy_perform(handle);
char *lt = NULL;
char *action = NULL;
private_auth_univ_orleans_get_action_and_lt(handle, &lt, &action);
if (lt == NULL || action == NULL) {
return 0;
}
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION,
private_auth_univ_orleans_dumb_write_callback);
private_auth_univ_orleans_post_login(handle, lt, action, username,
password);
free(lt);
free(action);
return 0;
}
int private_auth_univ_orleans_get_action_and_lt(CURL *handle, char **lt,
char **action) {
TidyDoc tdoc;
TidyBuffer docbuf = {0};
// TidyBuffer tidy_errbuf = {0};
int err;
curl_easy_setopt(
handle, CURLOPT_URL,
"https://auth.univ-orleans.fr/cas/login?service=https://"
"ent.univ-orleans.fr/uPortal/"
"Login%3FrefUrl%3D%2FuPortal%2Ff%2Faccueil%2Fnormal%2Frender.uPn");
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION,
private_auth_univ_orleans_tidy_buf_write_cb);
tdoc = tidyCreate();
tidyOptSetBool(tdoc, TidyShowWarnings, no);
tidyOptSetInt(tdoc, TidyWrapLen, 4096);
tidyBufInit(&docbuf);
tidyOptSetBool(tdoc, TidyQuiet, 1L);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &docbuf);
err = curl_easy_perform(handle);
if (!err) {
err = tidyParseBuffer(tdoc, &docbuf); /* parse the input */
if (err >= 0) {
private_auth_univ_orleans_get_action_and_lt_from_node(
tdoc, tidyGetRoot(tdoc), lt, action); /* walk the tree */
}
}
tidyBufFree(&docbuf);
// tidyBufFree(&tidy_errbuf);
tidyRelease(tdoc);
return 0;
}
int private_auth_univ_orleans_post_login(CURL *handle, char *lt, char *action,
char *username, char *password) {
char form_data[256];
char *encoded_lt = curl_easy_escape(handle, lt, strlen(lt));
char *encoded_username =
curl_easy_escape(handle, username, strlen(username));
char *encoded_password =
curl_easy_escape(handle, password, strlen(password));
int nbr = snprintf(
form_data, 256,
"lt=%s&username=%s&password=%s&_eventId=submit&submit=SE+CONNECTER",
encoded_lt, encoded_username, encoded_password);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, form_data);
curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, nbr);
curl_easy_setopt(handle, CURLOPT_POST, 1L);
int action_size = strlen(action);
char *url = (char *)calloc(28 + action_size + 1, sizeof(char));
strncpy(url, "https://auth.univ-orleans.fr", 29);
strncpy(url + 28, action, action_size);
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_perform(handle);
free(url);
curl_free(encoded_lt);
curl_free(encoded_username);
curl_free(encoded_password);
return 0;
}
int private_auth_univ_orleans_get_action_and_lt_from_node(TidyDoc doc,
TidyNode tnod,
char **lt,
char **action) {
TidyNode child;
for (child = tidyGetChild(tnod); child; child = tidyGetNext(child)) {
ctmbstr name = tidyNodeGetName(child);
if (name) {
TidyAttr attr;
int is_lt = 0;
int is_action = 0;
const char *value = NULL;
for (attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) {
if (!is_lt && !is_action &&
strcmp(tidyAttrName(attr), "name") == 0 &&
strcmp(tidyAttrValue(attr), "lt") == 0) // TODO OPTIMISE
{
is_lt = 1;
} else if (!is_action && !is_lt &&
strcmp(tidyAttrName(attr), "id") == 0 &&
strcmp(tidyAttrValue(attr), "fm1") ==
0) // TODO OPTIOMISE
{
is_action = 1;
} else if (strcmp(tidyAttrName(attr), "value") == 0) {
value = tidyAttrValue(attr);
} else if (!is_lt &&
strcmp(tidyAttrName(attr), "action") == 0) {
value = tidyAttrValue(attr);
}
}
if (is_lt && value != NULL) {
*lt = strdup(value);
} else if (is_action && value != NULL) {
*action = strdup(value);
}
}
if (*lt == NULL || *action == NULL) {
if (private_auth_univ_orleans_get_action_and_lt_from_node(
doc, child, lt, action)) {
return 1;
}
}
}
return *lt != NULL && *action != NULL;
}

148
src/cookie_iterator.c Normal file
View File

@ -0,0 +1,148 @@
#include <cookie_iterator.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#define STR_BUF_SIZE 256
cookie_iterator_t *new_cookie_iterator_from_curl(CURL *handle) {
struct cookie_iterator *iterator =
(struct cookie_iterator *)calloc(1, sizeof(struct cookie_iterator));
iterator->cookie_list = NULL;
int res =
curl_easy_getinfo(handle, CURLINFO_COOKIELIST, &iterator->cookie_list);
if (!res && iterator->cookie_list) {
iterator->current = iterator->cookie_list;
iterator->cookie = (struct cookie *)calloc(1, sizeof(struct cookie));
return iterator;
} else {
return NULL;
}
}
cookie_t *cookie_iterator_next(cookie_iterator_t *iterator) {
if (iterator->cookie_list == NULL) {
return NULL;
}
if (iterator->current != NULL) {
char *data = iterator->current->data;
char buf[STR_BUF_SIZE];
int offset = 0;
char c;
int i = 0;
while ((c = data[i]) && c != '\t' &&
i < sizeof(iterator->cookie->hostname) - 1) {
iterator->cookie->hostname[i] = c;
i++;
}
iterator->cookie->hostname[i] = '\0';
i++;
offset += i;
i = 0;
while ((c = data[offset + i]) && c != '\t' && i < STR_BUF_SIZE) {
buf[i] = c;
i++;
}
buf[i] = '\0';
i++;
offset += i;
if (strncmp(buf, "TRUE", 4) == 0) {
iterator->cookie->include_subdomains = 1;
} else {
iterator->cookie->include_subdomains = 0;
}
i = 0;
while ((c = data[offset + i]) && c != '\t' &&
i < sizeof(iterator->cookie->path) - 1) {
iterator->cookie->path[i] = c;
i++;
}
iterator->cookie->path[i] = '\0';
i++;
offset += i;
i = 0;
while ((c = data[offset + i]) && c != '\t' && i < STR_BUF_SIZE) {
buf[i] = c;
i++;
}
buf[i] = '\0';
i++;
offset += i;
if (strncmp(buf, "TRUE", 4) == 0) {
iterator->cookie->secure = 1;
} else {
iterator->cookie->secure = 0;
}
i = 0;
while ((c = data[offset + i]) && c != '\t' && i < STR_BUF_SIZE) {
buf[i] = c;
i++;
}
buf[i] = '\0';
i++;
offset += i;
iterator->cookie->expire = atol(buf);
i = 0;
while ((c = data[offset + i]) && c != '\t' &&
i < sizeof(iterator->cookie->name) - 1) {
iterator->cookie->name[i] = c;
i++;
}
iterator->cookie->name[i] = '\0';
i++;
offset += i;
i = 0;
while ((c = data[offset + i]) && c != '\t' &&
i < sizeof(iterator->cookie->value) - 1) {
iterator->cookie->value[i] = c;
i++;
}
iterator->cookie->value[i] = '\0';
iterator->current = iterator->current->next;
}
return (iterator->current != NULL) ? iterator->cookie : NULL;
}
void cookie_iterator_free(cookie_iterator_t *iterator) {
if (iterator->cookie_list != NULL) {
curl_slist_free_all(iterator->cookie_list);
iterator->cookie_list = NULL;
}
if (iterator->cookie != NULL) {
cookie_free(iterator->cookie);
iterator->cookie = NULL;
}
iterator->current = NULL;
free(iterator);
}
char *cookie_hostname(cookie_t *cookie) { return cookie->hostname; }
bool cookie_include_subdomains(cookie_t *cookie) {
return cookie->include_subdomains;
}
char *cookie_path(cookie_t *cookie) { return cookie->path; }
bool cookie_secure(cookie_t *cookie) { return cookie->secure; }
int cookie_expire(cookie_t *cookie) { return cookie->expire; }
char *cookie_name(cookie_t *cookie) { return cookie->name; }
char *cookie_value(cookie_t *cookie) { return cookie->value; }
void cookie_free(cookie_t *cookie) { free(cookie); }

31
src/test.c Normal file
View File

@ -0,0 +1,31 @@
#include <auth_univ_orleans.h>
#include <cookie_iterator.h>
#include <stdlib.h>
int main(void) {
char *username = getenv("USERNAME");
char *password = getenv("PASSWORD");
if (username == NULL || password == NULL) {
fprintf(stderr, "ERROR : missing USERNAME or PASSWORD env var\n");
return -1;
}
cookie_iterator_t *iter = auth_univ_get_session_token(username, password);
cookie_t *cookie;
while ((cookie = cookie_iterator_next(iter))) {
printf("%s :\n"
"\thostname: %s\n"
"\tinclude subdomains : %d\n"
"\tpath : %s\n"
"\tsecure : %d\n"
"\texpire : %d\n"
"\tvalue: %s\n",
cookie_name(cookie), cookie_hostname(cookie),
cookie_include_subdomains(cookie), cookie_path(cookie),
cookie_secure(cookie), cookie_expire(cookie), cookie_value(cookie));
}
cookie_iterator_free(iter);
}