]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Add `--save-to-keychain` option. keychain
authorYoshimasa Niwa <niw@niw.at>
Sun, 4 Nov 2018 07:53:37 +0000 (00:53 -0700)
committerYoshimasa Niwa <niw@niw.at>
Sun, 4 Nov 2018 08:02:17 +0000 (01:02 -0700)
main.c
openconnect-internal.h
openconnect.8.in

diff --git a/main.c b/main.c
index 2445ce31168d1dfc348f82d2985c4d93004a1032..195cae71b351b1c4560186cdf94dd261ba7e4c31 100644 (file)
--- a/main.c
+++ b/main.c
@@ -91,6 +91,7 @@ static int non_inter;
 static int cookieonly;
 static int allow_stdin_read;
 static char *keychain_account = NULL;
+static struct oc_text_list_item *keychain_saving_fields = NULL;
 
 static char *token_filename;
 static char *server_cert = NULL;
@@ -178,6 +179,7 @@ enum {
        OPT_PIDFILE,
        OPT_PASSWORD_ON_STDIN,
        OPT_USE_KEYCHAIN,
+       OPT_SAVE_TO_KEYCHAIN,
        OPT_PRINTCOOKIE,
        OPT_RECONNECT_TIMEOUT,
        OPT_SERVERCERT,
@@ -255,6 +257,7 @@ static const struct option long_options[] = {
        OPTION("passwd-on-stdin", 0, OPT_PASSWORD_ON_STDIN),
 #if ENABLE_KEYCHAIN
        OPTION("use-keychain", 1, OPT_USE_KEYCHAIN),
+       OPTION("save-to-keychain", 1, OPT_SAVE_TO_KEYCHAIN),
 #endif
        OPTION("no-passwd", 0, OPT_NO_PASSWD),
        OPTION("reconnect-timeout", 1, OPT_RECONNECT_TIMEOUT),
@@ -810,6 +813,7 @@ static void usage(void)
        printf("      --passwd-on-stdin           %s\n", _("Read password from standard input"));
 #if ENABLE_KEYCHAIN
        printf("      --use-keychain=ACCOUNT      %s\n", _("Look up Keychain to fill password form fields"));
+       printf("      --save-to-keychain=NAME     %s\n", _("Name of password form field to be saved to Keychain"));
 #endif
        printf("      --authgroup=GROUP           %s\n", _("Choose authentication login selection"));
        printf("  -c, --certificate=CERT          %s\n", _("Use SSL client certificate CERT"));
@@ -1301,6 +1305,13 @@ int main(int argc, char **argv)
                case OPT_USE_KEYCHAIN:
                        keychain_account = keep_config_arg();
                        break;
+               case OPT_SAVE_TO_KEYCHAIN: {
+                       struct oc_text_list_item *field = malloc(sizeof(*field));
+                       field->data = keep_config_arg();
+                       field->next = keychain_saving_fields;
+                       keychain_saving_fields = field;
+                       break;
+               }
 #endif
                case OPT_NO_PASSWD:
                        vpninfo->nopasswd = 1;
@@ -2007,26 +2018,31 @@ static char *lookup_keychain_password(const char *acc,
                size_t len = strlen(result);
                if (len == 0) goto end;
 
-               label = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("openconnect: %@ (%@)"), account, name);
-               if (!label) goto end;
-               data = CFDataCreate(kCFAllocatorDefault, (UInt8 *)result, len + 1);
-               if (!data) goto end;
+               for (struct oc_text_list_item *field = keychain_saving_fields; field; field = field->next) {
+                       if (strcmp(opt->name, field->data))
+                               continue;
 
-               CFDictionaryAddValue(query, kSecAttrLabel, label);
-               CFDictionaryAddValue(query, kSecValueData, data);
-               CFDictionaryRemoveValue(query, kSecReturnData);
+                       label = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("openconnect: %@ (%@)"), account, name);
+                       if (!label) goto end;
+                       data = CFDataCreate(kCFAllocatorDefault, (UInt8 *)result, len + 1);
+                       if (!data) goto end;
 
-               err = SecItemAdd(query, NULL);
-               if (err != errSecSuccess) {
-                       if (verbose > PRG_ERR)
-                               fprintf(stderr, "Failed to add item to Keychain error: %d\n", err);
-               } else {
-                       if (verbose > PRG_INFO)
-                               fprintf(stderr, "Item saved in Keychain\n");
+                       CFDictionaryAddValue(query, kSecAttrLabel, label);
+                       CFDictionaryAddValue(query, kSecValueData, data);
+                       CFDictionaryRemoveValue(query, kSecReturnData);
+
+                       err = SecItemAdd(query, NULL);
+                       if (err != errSecSuccess) {
+                               if (verbose > PRG_ERR)
+                                       fprintf(stderr, "Failed to add item to Keychain error: %d\n", err);
+                       } else {
+                               if (verbose > PRG_INFO)
+                                       fprintf(stderr, "Item saved in Keychain\n");
+                       }
+                       goto end;
                }
                goto end;
-       }
-       if (err != errSecSuccess) {
+       } else if (err != errSecSuccess) {
                if (verbose > PRG_ERR)
                        fprintf(stderr, "Failed to find item in Keychain error: %d\n", err);
                goto end;
index 8aa8fc89907d39eb7d59e53112fc5056d844533f..c6b8686e60b093074778afd8a9fbe3b8fbc46483 100644 (file)
@@ -197,6 +197,11 @@ struct oc_text_buf {
        int error;
 };
 
+struct oc_text_list_item {
+       char *data;
+       struct oc_text_list_item *next;
+};
+
 #define TLS_MASTER_KEY_SIZE 48
 
 #define RECONNECT_INTERVAL_MIN 10
index 2253f5bbd1bb788e60ff85a1ac50d13cc6506b81..437d374fde6d9683073ac36009e73792e036fbee 100644 (file)
@@ -58,6 +58,7 @@ openconnect \- Multi-protocol VPN client, for Cisco AnyConnect VPNs and others
 .OP \-\-non\-inter
 .OP \-\-passwd\-on\-stdin
 .OP \-\-use\-keychain string
+.OP \-\-save\-to\-keychain string
 .OP \-\-protocol proto
 .OP \-\-token\-mode mode
 .OP \-\-token\-secret {secret\fR[\fI,counter\fR]|@\fIfile\fR}
@@ -435,6 +436,19 @@ is a base name of Keychain items. For example, if
 is "companyvpn", it looks up Keychain item named "companyvpn:token" for
 "token" password form field.
 .TP
+.B \-\-save\-to\-keychain=NAME
+Name of password form field to be saved to Keychain.
+.I \-\-use\-keychain
+option is required.
+For example, if
+.I \-\-use\-keychain
+options's
+.I ACCOUNT
+is "companyvpn" and
+.I NAME
+is "token", it saves input value to Keychain item named "companyvpn:token" for
+"token" password form field.
+.TP
 .B \-\-protocol=PROTO
 Select VPN protocol
 .I PROTO