1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636 |
- /*
- * OpenConnect (SSL + DTLS) VPN client
- *
- * Copyright © 2013 Kevin Cernekee <cernekee@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- */
- #include <config.h>
- #include "openconnect.h"
- #include <jni.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- struct libctx {
- JNIEnv *jenv;
- jobject jobj;
- jobject async_lock;
- struct openconnect_info *vpninfo;
- int cmd_fd;
- int loglevel;
- };
- static void throw_excep(JNIEnv *jenv, const char *exc, int line)
- {
- jclass excep;
- char msg[64];
- snprintf(msg, 64, "%s:%d", __FILE__, line);
- (*jenv)->ExceptionClear(jenv);
- excep = (*jenv)->FindClass(jenv, exc);
- if (excep)
- (*jenv)->ThrowNew(jenv, excep, msg);
- }
- #define OOM(jenv) throw_excep(jenv, "java/lang/OutOfMemoryError", __LINE__)
- static struct libctx *getctx(JNIEnv *jenv, jobject jobj)
- {
- jclass jcls = (*jenv)->GetObjectClass(jenv, jobj);
- jfieldID jfld = (*jenv)->GetFieldID(jenv, jcls, "libctx", "J");
- if (!jfld)
- return NULL;
- return (void *)(unsigned long)(*jenv)->GetLongField(jenv, jobj, jfld);
- }
- /*
- * GetMethodID() and GetFieldID() and NewStringUTF() will automatically throw exceptions on error
- */
- static jmethodID get_obj_mid(struct libctx *ctx, jobject jobj, const char *name, const char *sig)
- {
- jclass jcls = (*ctx->jenv)->GetObjectClass(ctx->jenv, jobj);
- jmethodID mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, name, sig);
- return mid;
- }
- static jstring dup_to_jstring(JNIEnv *jenv, const char *in)
- {
- /*
- * Many implementations of NewStringUTF() will return NULL on
- * NULL input, but that isn't guaranteed:
- * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35979
- */
- return in ? (*jenv)->NewStringUTF(jenv, in) : NULL;
- }
- static int get_cstring(JNIEnv *jenv, jstring in, const char **out)
- {
- const char *tmp;
- if (in == NULL) {
- *out = NULL;
- return 0;
- }
- tmp = (*jenv)->GetStringUTFChars(jenv, in, NULL);
- if (!tmp) {
- OOM(jenv);
- return -1;
- }
- *out = tmp;
- return 0;
- }
- static void release_cstring(JNIEnv *jenv, jstring jstr, const char *cstr)
- {
- if (cstr)
- (*jenv)->ReleaseStringUTFChars(jenv, jstr, cstr);
- }
- static int set_int(struct libctx *ctx, jobject jobj, const char *name, int value)
- {
- jclass jcls = (*ctx->jenv)->GetObjectClass(ctx->jenv, jobj);
- jfieldID jfld = (*ctx->jenv)->GetFieldID(ctx->jenv, jcls, name, "I");
- if (!jfld)
- return -1;
- (*ctx->jenv)->SetIntField(ctx->jenv, jobj, jfld, value);
- return 0;
- }
- static int set_long(struct libctx *ctx, jobject jobj, const char *name, uint64_t value)
- {
- jclass jcls = (*ctx->jenv)->GetObjectClass(ctx->jenv, jobj);
- jfieldID jfld = (*ctx->jenv)->GetFieldID(ctx->jenv, jcls, name, "J");
- if (!jfld)
- return -1;
- (*ctx->jenv)->SetLongField(ctx->jenv, jobj, jfld, (jlong)value);
- return 0;
- }
- static int set_string(struct libctx *ctx, jobject jobj, const char *name, const char *value)
- {
- jclass jcls = (*ctx->jenv)->GetObjectClass(ctx->jenv, jobj);
- jfieldID jfld = (*ctx->jenv)->GetFieldID(ctx->jenv, jcls, name, "Ljava/lang/String;");
- jstring jarg;
- if (!jfld)
- return -1;
- jarg = dup_to_jstring(ctx->jenv, value);
- if (value && !jarg)
- return -1;
- (*ctx->jenv)->SetObjectField(ctx->jenv, jobj, jfld, jarg);
- return 0;
- }
- static int add_string(struct libctx *ctx, jclass jcls, jobject jobj,
- const char *name, const char *value)
- {
- jmethodID mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, name, "(Ljava/lang/String;)V");
- jstring jarg;
- if (!value)
- return 0;
- if (!mid)
- return -1;
- jarg = dup_to_jstring(ctx->jenv, value);
- if (!jarg)
- return -1;
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, jobj, mid, jarg);
- (*ctx->jenv)->DeleteLocalRef(ctx->jenv, jarg);
- return 0;
- }
- static int add_string_pair(struct libctx *ctx, jclass jcls, jobject jobj,
- const char *name, const char *key, const char *value)
- {
- jmethodID mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, name, "(Ljava/lang/String;Ljava/lang/String;)V");
- jstring jarg0, jarg1;
- if (!key || !value)
- return -1;
- if (!mid)
- return -1;
- jarg0 = dup_to_jstring(ctx->jenv, key);
- if (!jarg0)
- return -1;
- jarg1 = dup_to_jstring(ctx->jenv, value);
- if (!jarg1) {
- (*ctx->jenv)->DeleteLocalRef(ctx->jenv, jarg0);
- return -1;
- }
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, jobj, mid, jarg0, jarg1);
- (*ctx->jenv)->DeleteLocalRef(ctx->jenv, jarg1);
- (*ctx->jenv)->DeleteLocalRef(ctx->jenv, jarg0);
- return 0;
- }
- static int validate_peer_cert_cb(void *privdata, const char *reason)
- {
- struct libctx *ctx = privdata;
- jstring jreason;
- int ret = -1;
- jmethodID mid;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return -1;
- jreason = dup_to_jstring(ctx->jenv, reason);
- if (!jreason)
- goto out;
- mid = get_obj_mid(ctx, ctx->jobj, "onValidatePeerCert", "(Ljava/lang/String;)I");
- if (mid)
- ret = (*ctx->jenv)->CallIntMethod(ctx->jenv, ctx->jobj, mid, jreason);
- out:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return ret;
- }
- static int write_new_config_cb(void *privdata, const char *buf, int buflen)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- jbyteArray jbuf;
- int ret = -1;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return -1;
- mid = get_obj_mid(ctx, ctx->jobj, "onWriteNewConfig", "([B)I");
- if (!mid)
- goto out;
- jbuf = (*ctx->jenv)->NewByteArray(ctx->jenv, buflen);
- if (!jbuf)
- goto out;
- (*ctx->jenv)->SetByteArrayRegion(ctx->jenv, jbuf, 0, buflen, (jbyte *)buf);
- ret = (*ctx->jenv)->CallIntMethod(ctx->jenv, ctx->jobj, mid, jbuf);
- out:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return ret;
- }
- static void protect_socket_cb(void *privdata, int fd)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return;
- mid = get_obj_mid(ctx, ctx->jobj, "onProtectSocket", "(I)V");
- if (mid)
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, ctx->jobj, mid, fd);
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- }
- static void stats_cb(void *privdata, const struct oc_stats *stats)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- jclass jcls;
- jobject jobj = NULL;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return;
- jcls = (*ctx->jenv)->FindClass(ctx->jenv, "org/infradead/libopenconnect/LibOpenConnect$VPNStats");
- if (jcls == NULL)
- goto out;
- mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, "<init>", "()V");
- if (!mid)
- goto out;
- jobj = (*ctx->jenv)->NewObject(ctx->jenv, jcls, mid);
- if (!jobj)
- goto out;
- if (set_long(ctx, jobj, "txPkts", stats->tx_pkts) ||
- set_long(ctx, jobj, "txBytes", stats->tx_bytes) ||
- set_long(ctx, jobj, "rxPkts", stats->rx_pkts) ||
- set_long(ctx, jobj, "rxBytes", stats->rx_bytes))
- goto out;
- mid = get_obj_mid(ctx, ctx->jobj, "onStatsUpdate",
- "(Lorg/infradead/libopenconnect/LibOpenConnect$VPNStats;)V");
- if (mid)
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, ctx->jobj, mid, jobj);
- out:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- }
- static void setup_tun_cb(void *privdata)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return;
- mid = get_obj_mid(ctx, ctx->jobj, "onSetupTun", "()V");
- if (mid)
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, ctx->jobj, mid);
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- }
- static void reconnected_cb(void *privdata)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return;
- mid = get_obj_mid(ctx, ctx->jobj, "onReconnected", "()V");
- if (mid)
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, ctx->jobj, mid);
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- }
- static jobject new_auth_form(struct libctx *ctx, struct oc_auth_form *form)
- {
- jmethodID mid;
- jclass jcls;
- jobject jobj = NULL;
- jcls = (*ctx->jenv)->FindClass(ctx->jenv, "org/infradead/libopenconnect/LibOpenConnect$AuthForm");
- if (jcls == NULL)
- return NULL;
- mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, "<init>", "()V");
- if (!mid)
- return NULL;
- jobj = (*ctx->jenv)->NewObject(ctx->jenv, jcls, mid);
- if (!jobj)
- return NULL;
- if (set_string(ctx, jobj, "banner", form->banner) ||
- set_string(ctx, jobj, "message", form->message) ||
- set_string(ctx, jobj, "error", form->error) ||
- set_string(ctx, jobj, "authID", form->auth_id) ||
- set_string(ctx, jobj, "method", form->method) ||
- set_string(ctx, jobj, "action", form->action) ||
- set_int(ctx, jobj, "authgroupSelection", form->authgroup_selection)) {
- return NULL;
- }
- return jobj;
- }
- static jobject new_form_choice(struct libctx *ctx, struct oc_choice *choice)
- {
- jmethodID mid;
- jclass jcls;
- jobject jobj = NULL;
- jcls = (*ctx->jenv)->FindClass(ctx->jenv,
- "org/infradead/libopenconnect/LibOpenConnect$FormChoice");
- if (jcls == NULL)
- return NULL;
- mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, "<init>", "()V");
- if (!mid)
- return NULL;
- jobj = (*ctx->jenv)->NewObject(ctx->jenv, jcls, mid);
- if (!jobj)
- return NULL;
- if (set_string(ctx, jobj, "name", choice->name) ||
- set_string(ctx, jobj, "label", choice->label) ||
- set_string(ctx, jobj, "authType", choice->auth_type) ||
- set_string(ctx, jobj, "overrideName", choice->override_name) ||
- set_string(ctx, jobj, "overrideLabel", choice->override_label)) {
- return NULL;
- }
- return jobj;
- }
- static int populate_select_choices(struct libctx *ctx, jobject jopt, struct oc_form_opt_select *opt)
- {
- jmethodID mid;
- int i;
- mid = get_obj_mid(ctx, jopt, "addChoice",
- "(Lorg/infradead/libopenconnect/LibOpenConnect$FormChoice;)V");
- if (!mid)
- return -1;
- for (i = 0; i < opt->nr_choices; i++) {
- jobject jformchoice = new_form_choice(ctx, opt->choices[i]);
- if (!jformchoice)
- return -1;
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, jopt, mid, jformchoice);
- }
- return 0;
- }
- static int add_form_option(struct libctx *ctx, jobject jform, struct oc_form_opt *opt, int is_authgroup)
- {
- jmethodID addOpt;
- jobject jopt;
- addOpt = get_obj_mid(ctx, jform, "addOpt",
- "(Z)Lorg/infradead/libopenconnect/LibOpenConnect$FormOpt;");
- if (!addOpt)
- return -1;
- jopt = (*ctx->jenv)->CallObjectMethod(ctx->jenv, jform, addOpt, is_authgroup);
- if (jopt == NULL)
- return -1;
- if (set_int(ctx, jopt, "type", opt->type) ||
- set_string(ctx, jopt, "name", opt->name) ||
- set_string(ctx, jopt, "label", opt->label) ||
- set_string(ctx, jopt, "value", opt->_value) ||
- set_long(ctx, jopt, "flags", opt->flags))
- return -1;
- if (opt->type == OC_FORM_OPT_SELECT &&
- populate_select_choices(ctx, jopt, (struct oc_form_opt_select *)opt))
- return -1;
- return 0;
- }
- static char *lookup_choice_name(struct oc_form_opt_select *opt, const char *name)
- {
- int i;
- /* opt->_value is NOT a caller-allocated string for OC_FORM_OPT_SELECT */
- for (i = 0; i < opt->nr_choices; i++)
- if (!strcmp(opt->choices[i]->name, name))
- return opt->choices[i]->name;
- return NULL;
- }
- static int process_auth_form_cb(void *privdata, struct oc_auth_form *form)
- {
- struct libctx *ctx = privdata;
- jobject jform;
- jmethodID callback, getOptValue;
- struct oc_form_opt *opt;
- jint ret;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return -1;
- /* create and populate new AuthForm object and option/choice lists */
- jform = new_auth_form(ctx, form);
- if (!jform)
- goto err;
- getOptValue = get_obj_mid(ctx, jform, "getOptValue", "(Ljava/lang/String;)Ljava/lang/String;");
- if (!getOptValue)
- goto err;
- for (opt = form->opts; opt; opt = opt->next) {
- int is_authgroup = opt == (void *)form->authgroup_opt;
- if (add_form_option(ctx, jform, opt, is_authgroup) < 0)
- goto err;
- }
- /* invoke onProcessAuthForm callback */
- callback = get_obj_mid(ctx, ctx->jobj, "onProcessAuthForm",
- "(Lorg/infradead/libopenconnect/LibOpenConnect$AuthForm;)I");
- if (!callback)
- goto err;
- ret = (*ctx->jenv)->CallIntMethod(ctx->jenv, ctx->jobj, callback, jform);
- /* copy any populated form fields back into the C structs */
- for (opt = form->opts; opt; opt = opt->next) {
- jstring jname, jvalue;
- jname = dup_to_jstring(ctx->jenv, opt->name);
- if (!jname)
- goto err;
- jvalue = (*ctx->jenv)->CallObjectMethod(ctx->jenv, jform, getOptValue, jname);
- if (jvalue) {
- const char *tmp = (*ctx->jenv)->GetStringUTFChars(ctx->jenv, jvalue, NULL);
- if (!tmp)
- goto err;
- if (opt->type == OC_FORM_OPT_SELECT)
- opt->_value = lookup_choice_name((void *)opt, tmp);
- else {
- free(opt->_value);
- opt->_value = strdup(tmp);
- if (!opt->_value)
- OOM(ctx->jenv);
- }
- (*ctx->jenv)->ReleaseStringUTFChars(ctx->jenv, jvalue, tmp);
- }
- }
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return ret;
- err:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return -1;
- }
- static void __attribute__ ((format(printf, 3, 4)))
- progress_cb(void *privdata, int level, const char *fmt, ...)
- {
- struct libctx *ctx = privdata;
- va_list ap;
- char *msg;
- jstring jmsg;
- int ret, loglevel;
- jmethodID mid;
- (*ctx->jenv)->MonitorEnter(ctx->jenv, ctx->async_lock);
- loglevel = ctx->loglevel;
- (*ctx->jenv)->MonitorExit(ctx->jenv, ctx->async_lock);
- if (level > loglevel)
- return;
- va_start(ap, fmt);
- ret = vasprintf(&msg, fmt, ap);
- va_end(ap);
- if (ret < 0) {
- OOM(ctx->jenv);
- return;
- }
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return;
- jmsg = dup_to_jstring(ctx->jenv, msg);
- free(msg);
- if (!jmsg)
- goto out;
- mid = get_obj_mid(ctx, ctx->jobj, "onProgress", "(ILjava/lang/String;)V");
- if (mid)
- (*ctx->jenv)->CallVoidMethod(ctx->jenv, ctx->jobj, mid, level, jmsg);
- out:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- }
- static int lock_token_cb(void *privdata)
- {
- struct libctx *ctx = privdata;
- jmethodID mid;
- int ret = -1;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return -1;
- mid = get_obj_mid(ctx, ctx->jobj, "onTokenLock", "()I");
- if (mid)
- ret = (*ctx->jenv)->CallIntMethod(ctx->jenv, ctx->jobj, mid);
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return ret;
- }
- static int unlock_token_cb(void *privdata, const char *new_token)
- {
- struct libctx *ctx = privdata;
- jstring jtoken;
- int ret = -1;
- jmethodID mid;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- return -1;
- jtoken = dup_to_jstring(ctx->jenv, new_token);
- if (!jtoken)
- goto out;
- mid = get_obj_mid(ctx, ctx->jobj, "onTokenUnlock", "(Ljava/lang/String;)I");
- if (mid)
- ret = (*ctx->jenv)->CallIntMethod(ctx->jenv, ctx->jobj, mid, jtoken);
- out:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- return ret;
- }
- /* Library init/uninit */
- static jobject init_async_lock(struct libctx *ctx)
- {
- jclass jcls = (*ctx->jenv)->GetObjectClass(ctx->jenv, ctx->jobj);
- jfieldID jfld = (*ctx->jenv)->GetFieldID(ctx->jenv, jcls, "asyncLock", "Ljava/lang/Object;");
- jobject jobj = (*ctx->jenv)->GetObjectField(ctx->jenv, ctx->jobj, jfld);
- if (jobj)
- jobj = (*ctx->jenv)->NewGlobalRef(ctx->jenv, jobj);
- return jobj;
- }
- JNIEXPORT jlong JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_init(
- JNIEnv *jenv, jobject jobj, jstring juseragent)
- {
- char *useragent;
- struct libctx *ctx = calloc(1, sizeof(*ctx));
- if (!ctx)
- goto bad;
- ctx->jenv = jenv;
- ctx->jobj = (*jenv)->NewGlobalRef(jenv, jobj);
- if (!ctx->jobj)
- goto bad_free_ctx;
- ctx->async_lock = init_async_lock(ctx);
- if (!ctx->async_lock)
- goto bad_delete_obj_ref;
- useragent = (char *)(*jenv)->GetStringUTFChars(jenv, juseragent, NULL);
- if (!useragent)
- goto bad_delete_ref;
- ctx->vpninfo = openconnect_vpninfo_new(useragent, validate_peer_cert_cb,
- write_new_config_cb, process_auth_form_cb,
- progress_cb, ctx);
- (*jenv)->ReleaseStringUTFChars(jenv, juseragent, useragent);
- if (!ctx->vpninfo)
- goto bad_delete_ref;
- openconnect_set_token_callbacks(ctx->vpninfo, ctx, lock_token_cb,
- unlock_token_cb);
- openconnect_set_protect_socket_handler(ctx->vpninfo, protect_socket_cb);
- openconnect_set_stats_handler(ctx->vpninfo, stats_cb);
- openconnect_set_setup_tun_handler(ctx->vpninfo, setup_tun_cb);
- openconnect_set_reconnected_handler(ctx->vpninfo, reconnected_cb);
- ctx->cmd_fd = openconnect_setup_cmd_pipe(ctx->vpninfo);
- if (ctx->cmd_fd < 0)
- goto bad_free_vpninfo;
- ctx->loglevel = PRG_DEBUG;
- return (jlong)(unsigned long)ctx;
- bad_free_vpninfo:
- openconnect_vpninfo_free(ctx->vpninfo);
- bad_delete_ref:
- (*jenv)->DeleteGlobalRef(jenv, ctx->async_lock);
- bad_delete_obj_ref:
- (*jenv)->DeleteGlobalRef(jenv, ctx->jobj);
- bad_free_ctx:
- free(ctx);
- bad:
- OOM(jenv);
- return 0;
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_free(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_vpninfo_free(ctx->vpninfo);
- (*jenv)->DeleteGlobalRef(jenv, ctx->async_lock);
- (*jenv)->DeleteGlobalRef(jenv, ctx->jobj);
- free(ctx);
- }
- static void write_cmd_pipe(JNIEnv *jenv, jobject jobj, char cmd)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- if (write(ctx->cmd_fd, &cmd, 1) < 0) {
- /* probably dead already */
- }
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_doCancel(
- JNIEnv *jenv, jobject jobj)
- {
- write_cmd_pipe(jenv, jobj, OC_CMD_CANCEL);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_pause(
- JNIEnv *jenv, jobject jobj)
- {
- write_cmd_pipe(jenv, jobj, OC_CMD_PAUSE);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_requestStats(
- JNIEnv *jenv, jobject jobj)
- {
- write_cmd_pipe(jenv, jobj, OC_CMD_STATS);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_globalInit(
- JNIEnv *jenv, jclass jcls)
- {
- openconnect_init_ssl();
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_obtainCookie(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return 0;
- return openconnect_obtain_cookie(ctx->vpninfo);
- }
- /* special handling: caller-allocated buffer */
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getPeerCertHash(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- const char *hash;
- jstring jresult = NULL;
- if (!ctx)
- return NULL;
- hash = openconnect_get_peer_cert_hash(ctx->vpninfo);
- if (!hash)
- return NULL;
- jresult = dup_to_jstring(ctx->jenv, hash);
- if (!jresult)
- OOM(ctx->jenv);
- return jresult;
- }
- /* special handling: callee-allocated, caller-freed string */
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getPeerCertDetails(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- char *buf = NULL;
- jstring jresult = NULL;
- if (!ctx)
- return NULL;
- buf = openconnect_get_peer_cert_details(ctx->vpninfo);
- if (!buf)
- return NULL;
- jresult = dup_to_jstring(ctx->jenv, buf);
- if (!jresult)
- OOM(ctx->jenv);
- openconnect_free_cert_info(ctx->vpninfo, buf);
- return jresult;
- }
- /* special handling: callee-allocated, caller-freed binary buffer */
- JNIEXPORT jbyteArray JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getPeerCertDER(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- unsigned char *buf = NULL;
- int ret;
- jbyteArray jresult = NULL;
- if (!ctx)
- return NULL;
- ret = openconnect_get_peer_cert_DER(ctx->vpninfo, &buf);
- if (ret < 0)
- return NULL;
- jresult = (*ctx->jenv)->NewByteArray(ctx->jenv, ret);
- if (jresult)
- (*ctx->jenv)->SetByteArrayRegion(ctx->jenv, jresult, 0, ret, (jbyte *) buf);
- openconnect_free_cert_info(ctx->vpninfo, buf);
- return jresult;
- }
- /* special handling: callee-allocated, caller-freed binary buffer */
- JNIEXPORT jbyteArray JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getPeerCertChain(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- struct oc_cert *chain = NULL, *p;
- int cert_list_size, i;
- jobjectArray jresult = NULL;
- jclass jcls;
- if (!ctx)
- goto err;
- cert_list_size = openconnect_get_peer_cert_chain(ctx->vpninfo, &chain);
- if (cert_list_size <= 0)
- goto err;
- jcls = (*ctx->jenv)->FindClass(ctx->jenv, "[B");
- if (!jcls)
- goto err;
- jresult = (*ctx->jenv)->NewObjectArray(ctx->jenv, cert_list_size, jcls, NULL);
- if (!jresult)
- goto err;
- if ((*ctx->jenv)->PushLocalFrame(ctx->jenv, 256) < 0)
- goto err;
- for (i = 0, p = chain; i < cert_list_size; i++, p++) {
- jbyteArray cert = (*ctx->jenv)->NewByteArray(ctx->jenv, p->der_len);
- if (!cert)
- goto err2;
- (*ctx->jenv)->SetByteArrayRegion(ctx->jenv, cert, 0, p->der_len, (jbyte *)p->der_data);
- (*ctx->jenv)->SetObjectArrayElement(ctx->jenv, jresult, i, cert);
- }
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- openconnect_free_peer_cert_chain(ctx->vpninfo, chain);
- return jresult;
- err2:
- (*ctx->jenv)->PopLocalFrame(ctx->jenv, NULL);
- err:
- if (jresult)
- (*ctx->jenv)->DeleteLocalRef(ctx->jenv, jresult);
- if (chain)
- openconnect_free_peer_cert_chain(ctx->vpninfo, chain);
- return NULL;
- }
- /* special handling: two string arguments */
- JNIEXPORT int JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setClientCert(
- JNIEnv *jenv, jobject jobj, jstring jcert, jstring jsslkey)
- {
- int ret;
- struct libctx *ctx = getctx(jenv, jobj);
- const char *cert = NULL, *sslkey = NULL;
- if (!ctx)
- return -EINVAL;
- if (get_cstring(ctx->jenv, jcert, &cert) ||
- get_cstring(ctx->jenv, jsslkey, &sslkey))
- return -ENOMEM;
- ret = openconnect_set_client_cert(ctx->vpninfo, cert, sslkey);
- release_cstring(ctx->jenv, jcert, cert);
- release_cstring(ctx->jenv, jsslkey, sslkey);
- return ret;
- }
- JNIEXPORT int JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setMCACert(
- JNIEnv *jenv, jobject jobj, jstring jcert, jstring jsslkey)
- {
- int ret;
- struct libctx *ctx = getctx(jenv, jobj);
- const char *cert = NULL, *sslkey = NULL;
- if (!ctx)
- return -EINVAL;
- if (get_cstring(ctx->jenv, jcert, &cert) ||
- get_cstring(ctx->jenv, jsslkey, &sslkey))
- return -ENOMEM;
- ret = openconnect_set_mca_cert(ctx->vpninfo, cert, sslkey);
- release_cstring(ctx->jenv, jcert, cert);
- release_cstring(ctx->jenv, jsslkey, sslkey);
- return ret;
- }
- /* special handling: multiple string arguments */
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setupTunDevice(
- JNIEnv *jenv, jobject jobj, jstring jarg0, jstring jarg1)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- const char *arg0 = NULL, *arg1 = NULL;
- int ret = -ENOMEM;
- if (!ctx)
- return -EINVAL;
- if (!get_cstring(ctx->jenv, jarg0, &arg0) &&
- !get_cstring(ctx->jenv, jarg1, &arg1))
- ret = openconnect_setup_tun_device(ctx->vpninfo, arg0, arg1);
- release_cstring(ctx->jenv, jarg0, arg0);
- release_cstring(ctx->jenv, jarg1, arg1);
- return ret;
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setCSDWrapper(
- JNIEnv *jenv, jobject jobj, jstring jarg0, jstring jarg1, jstring jarg2)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- const char *arg0 = NULL, *arg1 = NULL, *arg2 = NULL;
- if (!ctx)
- return;
- if (!get_cstring(ctx->jenv, jarg0, &arg0) &&
- !get_cstring(ctx->jenv, jarg1, &arg1) &&
- !get_cstring(ctx->jenv, jarg2, &arg2)) {
- openconnect_setup_csd(ctx->vpninfo, getuid(), 1, arg0);
- if (arg1) openconnect_set_csd_environ(ctx->vpninfo, "TMPDIR", arg1);
- if (arg2) openconnect_set_csd_environ(ctx->vpninfo, "PATH", arg2);
- }
- release_cstring(ctx->jenv, jarg0, arg0);
- release_cstring(ctx->jenv, jarg1, arg1);
- release_cstring(ctx->jenv, jarg2, arg2);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setMobileInfo(
- JNIEnv *jenv, jobject jobj, jstring jarg0, jstring jarg1, jstring jarg2)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- const char *arg0 = NULL, *arg1 = NULL, *arg2 = NULL;
- if (!ctx)
- return;
- if (!get_cstring(ctx->jenv, jarg0, &arg0) &&
- !get_cstring(ctx->jenv, jarg1, &arg1) &&
- !get_cstring(ctx->jenv, jarg2, &arg2))
- openconnect_set_mobile_info(ctx->vpninfo, arg0, arg1, arg2);
- release_cstring(ctx->jenv, jarg0, arg0);
- release_cstring(ctx->jenv, jarg1, arg1);
- release_cstring(ctx->jenv, jarg2, arg2);
- }
- /* class methods (general library info) */
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getVersion(
- JNIEnv *jenv, jclass jcls)
- {
- return dup_to_jstring(jenv, openconnect_get_version());
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasPKCS11Support(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_pkcs11_support();
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasTSSBlobSupport(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_tss_blob_support();
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasTSS2BlobSupport(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_tss2_blob_support();
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasStokenSupport(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_stoken_support();
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasOATHSupport(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_oath_support();
- }
- JNIEXPORT jboolean JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_hasYubiOATHSupport(
- JNIEnv *jenv, jclass jcls)
- {
- return openconnect_has_yubioath_support();
- }
- /* simple cases: void or int params */
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getPort(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_get_port(ctx->vpninfo);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_passphraseFromFSID(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_passphrase_from_fsid(ctx->vpninfo);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_clearCookie(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_clear_cookie(ctx->vpninfo);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_resetSSL(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_reset_ssl(ctx->vpninfo);
- }
- JNIEXPORT int JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_disableIPv6(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_disable_ipv6(ctx->vpninfo);
- }
- JNIEXPORT int JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_disableDTLS(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_disable_dtls(ctx->vpninfo);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setCertExpiryWarning(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_cert_expiry_warning(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setReqMTU(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_reqmtu(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setDPD(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_dpd(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setTrojanInterval(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_trojan_interval(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setPassTOS(
- JNIEnv *jenv, jobject jobj, jboolean arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_pass_tos(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setPFS(
- JNIEnv *jenv, jobject jobj, jboolean arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_pfs(ctx->vpninfo, arg);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setAllowInsecureCrypto(
- JNIEnv *jenv, jobject jobj, jboolean arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_set_allow_insecure_crypto(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setSystemTrust(
- JNIEnv *jenv, jobject jobj, jboolean arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_system_trust(ctx->vpninfo, arg);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_makeCSTPConnection(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_make_cstp_connection(ctx->vpninfo);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setupDTLS(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_setup_dtls(ctx->vpninfo, arg);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_mainloop(
- JNIEnv *jenv, jobject jobj, jint arg0, jint arg1)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_mainloop(ctx->vpninfo, arg0, arg1);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setLogLevel(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- (*ctx->jenv)->MonitorEnter(ctx->jenv, ctx->async_lock);
- ctx->loglevel = arg;
- (*ctx->jenv)->MonitorExit(ctx->jenv, ctx->async_lock);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setupTunFD(
- JNIEnv *jenv, jobject jobj, jint arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_setup_tun_fd(ctx->vpninfo, arg);
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setXMLPost(
- JNIEnv *jenv, jobject jobj, jboolean arg)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return;
- openconnect_set_xmlpost(ctx->vpninfo, arg);
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getIdleTimeout(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- if (!ctx)
- return -EINVAL;
- return openconnect_get_idle_timeout(ctx->vpninfo);
- }
- JNIEXPORT jobject JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getAuthExpiration(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- jmethodID mid;
- jobject result;
- jclass jcls;
- time_t auth_expiration;
- if (!ctx)
- return NULL;
- auth_expiration = openconnect_get_auth_expiration(ctx->vpninfo);
- jcls = (*ctx->jenv)->FindClass(ctx->jenv, "java/time/Instant");
- if (jcls == NULL)
- goto err;
- mid = (*jenv)->GetStaticMethodID(jenv, jcls, "ofEpochSecond", "(J)Ljava/time/Instant;");
- if (!mid)
- goto err;
- result = (*jenv)->CallStaticObjectMethod(jenv, jcls, mid, auth_expiration);
- if (result == NULL)
- goto err;
- return result;
- err:
- return NULL;
- }
- /* simple cases: return a const string (no need to free it) */
- #define RETURN_STRING_START \
- struct libctx *ctx = getctx(jenv, jobj); \
- const char *buf = NULL; \
- jstring jresult = NULL; \
- if (!ctx) \
- return NULL; \
- #define RETURN_STRING_END \
- if (!buf) \
- return NULL; \
- jresult = dup_to_jstring(ctx->jenv, buf); \
- if (!jresult) \
- OOM(ctx->jenv); \
- return jresult;
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getHostname(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_hostname(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getDNSName(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_dnsname(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getUrlpath(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_urlpath(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getCookie(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_cookie(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getIFName(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_ifname(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getDTLSCipher(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_dtls_cipher(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getDTLSCompression(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_dtls_compression(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getCSTPCompression(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_cstp_compression(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getCSTPCipher(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_cstp_cipher(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getProtocol(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_protocol(ctx->vpninfo);
- RETURN_STRING_END
- }
- JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getConnectUrl(
- JNIEnv *jenv, jobject jobj)
- {
- RETURN_STRING_START
- buf = openconnect_get_connect_url(ctx->vpninfo);
- RETURN_STRING_END
- }
- #define SET_STRING_START() \
- struct libctx *ctx = getctx(jenv, jobj); \
- const char *arg = NULL; \
- if (!ctx) \
- return -EINVAL; \
- if (get_cstring(ctx->jenv, jarg, &arg)) \
- return -ENOMEM;
- #define SET_STRING_START_VOID() \
- struct libctx *ctx = getctx(jenv, jobj); \
- const char *arg = NULL; \
- if (!ctx) \
- return; \
- if (get_cstring(ctx->jenv, jarg, &arg)) \
- return;
- #define SET_STRING_END() \
- release_cstring(ctx->jenv, jarg, arg)
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_checkPeerCertHash(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_check_peer_cert_hash(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_parseURL(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_parse_url(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setProxyAuth(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_set_proxy_auth(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setHTTPProxy(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_set_http_proxy(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setProtocol(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_set_protocol(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setXMLSHA1(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_xmlsha1(ctx->vpninfo, arg, strlen(arg) + 1);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setHostname(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_hostname(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setVersionString(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_version_string(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setUsergent(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_useragent(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setUrlpath(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_urlpath(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setCookie(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_cookie(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setLocalName(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_localname(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setCAFile(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START_VOID()
- openconnect_set_cafile(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setReportedOS(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- SET_STRING_START()
- return openconnect_set_reported_os(ctx->vpninfo, arg);
- SET_STRING_END();
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setTokenMode(
- JNIEnv *jenv, jobject jobj, jint mode, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_set_token_mode(ctx->vpninfo, mode, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setupTunScript(
- JNIEnv *jenv, jobject jobj, jstring jarg)
- {
- int ret;
- SET_STRING_START()
- ret = openconnect_setup_tun_script(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jobject JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getIPInfo(
- JNIEnv *jenv, jobject jobj)
- {
- struct libctx *ctx = getctx(jenv, jobj);
- jmethodID mid;
- jclass jcls;
- const struct oc_ip_info *ip;
- const struct oc_vpn_option *cstp, *dtls;
- struct oc_split_include *inc;
- int i;
- if (!ctx)
- return NULL;
- if (openconnect_get_ip_info(ctx->vpninfo, &ip, &cstp, &dtls) < 0)
- return NULL;
- if (!ip)
- return NULL;
- jcls = (*ctx->jenv)->FindClass(ctx->jenv,
- "org/infradead/libopenconnect/LibOpenConnect$IPInfo");
- if (jcls == NULL)
- return NULL;
- mid = (*ctx->jenv)->GetMethodID(ctx->jenv, jcls, "<init>", "()V");
- if (!mid)
- return NULL;
- jobj = (*ctx->jenv)->NewObject(ctx->jenv, jcls, mid);
- if (!jobj)
- return NULL;
- if (set_string(ctx, jobj, "addr", ip->addr) ||
- set_string(ctx, jobj, "netmask", ip->netmask) ||
- set_string(ctx, jobj, "addr6", ip->addr6) ||
- set_string(ctx, jobj, "netmask6", ip->netmask6) ||
- set_string(ctx, jobj, "domain", ip->domain) ||
- set_string(ctx, jobj, "proxyPac", ip->proxy_pac) ||
- set_string(ctx, jobj, "gatewayAddr", ip->gateway_addr) ||
- set_int(ctx, jobj, "MTU", ip->mtu))
- return NULL;
- for (i = 0; i < 3; i++) {
- if (ip->dns[i] && add_string(ctx, jcls, jobj, "addDNS", ip->dns[i]))
- return NULL;
- if (ip->nbns[i] && add_string(ctx, jcls, jobj, "addNBNS", ip->nbns[i]))
- return NULL;
- }
- for (inc = ip->split_dns; inc; inc = inc->next)
- if (add_string(ctx, jcls, jobj, "addSplitDNS", inc->route))
- return NULL;
- for (inc = ip->split_includes; inc; inc = inc->next)
- if (add_string(ctx, jcls, jobj, "addSplitInclude", inc->route))
- return NULL;
- for (inc = ip->split_excludes; inc; inc = inc->next)
- if (add_string(ctx, jcls, jobj, "addSplitExclude", inc->route))
- return NULL;
- for (; cstp; cstp = cstp->next)
- if (add_string_pair(ctx, jcls, jobj, "addCSTPOption", cstp->option, cstp->value))
- return NULL;
- for (; dtls; dtls = dtls->next)
- if (add_string_pair(ctx, jcls, jobj, "addDTLSOption", dtls->option, dtls->value))
- return NULL;
- return jobj;
- }
- JNIEXPORT jobjectArray JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getSupportedProtocols(
- JNIEnv *jenv, jclass jcls)
- {
- jmethodID mid;
- jobjectArray result;
- struct libctx ctx = { .jenv = jenv, .jobj = NULL, .async_lock = NULL, .vpninfo = NULL, .cmd_fd = -1, .loglevel = -1 };
- /* call C library */
- struct oc_vpn_proto *protos;
- int np, ii;
- np = openconnect_get_supported_protocols(&protos);
- if (np < 0)
- return NULL;
- /* get VPNProto class, its init method, and create array */
- jcls = (*jenv)->FindClass(jenv,
- "org/infradead/libopenconnect/LibOpenConnect$VPNProto");
- if (jcls == NULL)
- goto err;
- mid = (*jenv)->GetMethodID(jenv, jcls, "<init>", "()V");
- if (!mid)
- goto err;
- result = (*jenv)->NewObjectArray(jenv, np, jcls, NULL);
- if (result == NULL)
- goto nomem;
- for (ii=0; ii<np; ii++) {
- jobject jobj = (*jenv)->NewObject(jenv, jcls, mid);
- if (!jobj)
- goto nomem;
- if (set_string(&ctx, jobj, "name", protos[ii].name) ||
- set_string(&ctx, jobj, "prettyName", protos[ii].pretty_name) ||
- set_string(&ctx, jobj, "description", protos[ii].description) ||
- set_int (&ctx, jobj, "flags", protos[ii].flags))
- goto nomem;
- (*jenv)->SetObjectArrayElement(jenv, result, ii, jobj);
- }
- openconnect_free_supported_protocols(protos);
- return result;
- nomem:
- OOM(jenv);
- err:
- openconnect_free_supported_protocols(protos);
- return NULL;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setKeyPassword(
- JNIEnv *jenv, jobject jobj, jstring jarg, jstring jarg2)
- {
- int ret;
- SET_STRING_START();
- ret = openconnect_set_key_password(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
- JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setMCAKeyPassword(
- JNIEnv *jenv, jobject jobj, jstring jarg, jstring jarg2)
- {
- int ret;
- SET_STRING_START();
- ret = openconnect_set_mca_key_password(ctx->vpninfo, arg);
- SET_STRING_END();
- return ret;
- }
|