Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package google-guest-oslogin for 
openSUSE:Factory checked in at 2023-08-16 14:17:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/google-guest-oslogin (Old)
 and      /work/SRC/openSUSE:Factory/.google-guest-oslogin.new.11712 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "google-guest-oslogin"

Wed Aug 16 14:17:45 2023 rev:19 rq:1104089 version:20230808.00

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/google-guest-oslogin/google-guest-oslogin.changes    
    2023-05-10 16:18:03.150807190 +0200
+++ 
/work/SRC/openSUSE:Factory/.google-guest-oslogin.new.11712/google-guest-oslogin.changes
     2023-08-16 14:17:46.659263726 +0200
@@ -1,0 +2,6 @@
+Tue Aug 15 13:53:44 UTC 2023 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to version 20230808.00
+  * byoid: extract and apply the ca fingerprint to policy call (#106)
+
+-------------------------------------------------------------------

Old:
----
  google-guest-oslogin-20230502.00.tar.gz

New:
----
  google-guest-oslogin-20230808.00.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ google-guest-oslogin.spec ++++++
--- /var/tmp/diff_new_pack.5PLPIA/_old  2023-08-16 14:17:47.971272912 +0200
+++ /var/tmp/diff_new_pack.5PLPIA/_new  2023-08-16 14:17:48.011273191 +0200
@@ -19,7 +19,7 @@
 %{!?_pam_moduledir: %define _pam_moduledir %{_pamdir}}
 
 Name:           google-guest-oslogin
-Version:        20230502.00
+Version:        20230808.00
 Release:        0
 Summary:        Google Cloud Guest OS Login
 License:        Apache-2.0

++++++ google-guest-oslogin-20230502.00.tar.gz -> 
google-guest-oslogin-20230808.00.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-oslogin-20230502.00/.gitignore 
new/guest-oslogin-20230808.00/.gitignore
--- old/guest-oslogin-20230502.00/.gitignore    1970-01-01 01:00:00.000000000 
+0100
+++ new/guest-oslogin-20230808.00/.gitignore    2023-08-08 20:00:56.000000000 
+0200
@@ -0,0 +1,7 @@
+*.so
+*.o
+google_authorized_keys
+google_authorized_keys_sk
+google_oslogin_nss_cache
+test/sshca_runner
+test/test_detail.xml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-oslogin-20230502.00/src/Makefile 
new/guest-oslogin-20230808.00/src/Makefile
--- old/guest-oslogin-20230502.00/src/Makefile  2023-05-02 20:42:44.000000000 
+0200
+++ new/guest-oslogin-20230808.00/src/Makefile  2023-08-08 20:00:56.000000000 
+0200
@@ -1,7 +1,7 @@
 SHELL = /bin/sh
 TOPDIR = $(realpath ..)
 
-CPPFLAGS = -Iinclude -I/usr/include/json-c
+CPPFLAGS = -Iinclude -I/usr/include/json-c -I$(TOPDIR)/third_party/include
 FLAGS = -fPIC -Wall -g
 CFLAGS = $(FLAGS) -Wstrict-prototypes
 CXXFLAGS = $(FLAGS)
@@ -53,10 +53,10 @@
 
 # PAM modules
 
-$(PAM_LOGIN): pam/pam_oslogin_login.o oslogin_utils.o
+$(PAM_LOGIN): pam/pam_oslogin_login.o pam/oslogin_sshca.o oslogin_utils.o 
include/oslogin_sshca.h
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
 
-$(PAM_ADMIN): pam/pam_oslogin_admin.o oslogin_utils.o
+$(PAM_ADMIN): pam/pam_oslogin_admin.o pam/oslogin_sshca.o oslogin_utils.o 
include/oslogin_sshca.h
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
 
 # Utilities.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-oslogin-20230502.00/src/include/oslogin_sshca.h 
new/guest-oslogin-20230808.00/src/include/oslogin_sshca.h
--- old/guest-oslogin-20230502.00/src/include/oslogin_sshca.h   1970-01-01 
01:00:00.000000000 +0100
+++ new/guest-oslogin-20230808.00/src/include/oslogin_sshca.h   2023-08-08 
20:00:56.000000000 +0200
@@ -0,0 +1,53 @@
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _OSLOGIN_SSHCA_H_
+#define _OSLOGIN_SSHCA_H_ 1
+
+#include <compat.h>
+#include <ctype.h>
+#include <security/pam_modules.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SKIP_BYTES(b, l, s)                     \
+  {                                             \
+    b = b + s;                                  \
+    l = l - s;                                  \
+  }                                             \
+
+#define SKIP_UINT64(b, l)                       \
+  SKIP_BYTES(b, l, 8)                           \
+
+#define SKIP_UINT32(b, l)                       \
+  SKIP_BYTES(b, l, 4)                           \
+
+#define PEEK_U32(p)                                     \
+  (((u_int32_t)(((const u_char *)(p))[0]) << 24) |      \
+   ((u_int32_t)(((const u_char *)(p))[1]) << 16) |      \
+   ((u_int32_t)(((const u_char *)(p))[2]) << 8) |       \
+   (u_int32_t)(((const u_char *)(p))[3]))
+
+int sshca_get_byoid_fingerprint(pam_handle_t* pamh, const char *blob, char 
**fingerprint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-oslogin-20230502.00/src/pam/oslogin_sshca.cc 
new/guest-oslogin-20230808.00/src/pam/oslogin_sshca.cc
--- old/guest-oslogin-20230502.00/src/pam/oslogin_sshca.cc      1970-01-01 
01:00:00.000000000 +0100
+++ new/guest-oslogin-20230808.00/src/pam/oslogin_sshca.cc      2023-08-08 
20:00:56.000000000 +0200
@@ -0,0 +1,322 @@
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <oslogin_sshca.h>
+#include <openbsd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sshca_type {
+  const char *type;
+  int (*skip_custom_fields)(char **buff, size_t *blen);
+} sshca_type;
+
+static int sshca_dsa_skip_fields(char **buff, size_t *blen);
+static int sshca_ecdsa_skip_fields(char **buff, size_t *blen);
+static int sshca_ed25519_skip_fields(char **buff, size_t *blen);
+static int sshca_rsa_skip_fields(char **buff, size_t *blen);
+
+static sshca_type sshca_impl[] = {
+    {"ecdsa-sha2-nistp256-cert-...@openssh.com", sshca_ecdsa_skip_fields},
+    {"ecdsa-sha2-nistp384-cert-...@openssh.com", sshca_ecdsa_skip_fields},
+    {"ecdsa-sha2-nistp521-cert-...@openssh.com", sshca_ecdsa_skip_fields},
+    {"rsa-sha2-256-cert-...@openssh.com", sshca_rsa_skip_fields},
+    {"rsa-sha2-512-cert-...@openssh.com", sshca_rsa_skip_fields},
+    {"ssh-dss-cert-...@openssh.com", sshca_dsa_skip_fields},
+    {"ssh-ed25519-cert-...@openssh.com", sshca_ed25519_skip_fields},
+    {"ssh-rsa-cert-...@openssh.com", sshca_rsa_skip_fields},
+    { },
+};
+
+static int
+sshca_get_string(char **buff, size_t *blen, char **ptr, size_t *len_ptr) {
+  u_int32_t len;
+
+  if (*blen < 4) {
+    return -1;
+  }
+
+  len = PEEK_U32(*buff);
+  if ((*blen - 4) < len) {
+    return -1;
+  }
+
+  if (len_ptr != NULL) {
+    *len_ptr = len;
+  }
+
+  *buff = *buff + 4;
+  *blen = *blen - 4;
+
+  if (ptr != NULL) {
+    *ptr = (char *)malloc(len + 1);
+    memcpy(*ptr, *buff, len);
+    ((char *)*ptr)[len] = '\0';
+  }
+
+  // Always move the buffer forward.
+  *buff = *buff + len;
+
+  return 0;
+}
+
+static sshca_type*
+sshca_get_implementation(const char *type) {
+  sshca_type *iter;
+
+  for (iter = sshca_impl; iter->type != NULL; iter++) {
+    if (strcasecmp(type, iter->type) == 0) {
+      return iter;
+    }
+  }
+
+  return NULL;
+}
+
+static int
+sshca_rsa_skip_fields(char **buff, size_t *blen) {
+  // Skip e.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  // Skip n.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+static int
+sshca_dsa_skip_fields(char **buff, size_t *blen) {
+  // Skip p.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  // Skip q.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  // Skip g.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  // Skip y.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+static int
+sshca_ed25519_skip_fields(char **buff, size_t *blen) {
+  // Skip pk.
+  return sshca_get_string(buff, blen, NULL, NULL);
+}
+
+static int
+sshca_ecdsa_skip_fields(char **buff, size_t *blen) {
+  // Skip curve.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  // Skip public key.
+  if (sshca_get_string(buff, blen, NULL, NULL) < 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+static int
+sshca_get_extension(pam_handle_t *pamh, const char *key, size_t k_len, char 
**exts) {
+  sshca_type* impl = NULL;
+  size_t n_len, t_len, tmp_exts_len, ret = -1;
+  char *tmp_exts, *tmp_head, *type, *key_b64, *head;
+
+  head = tmp_head = NULL;
+
+  head = key_b64 = (char *)calloc(k_len, sizeof(char));
+  if (key_b64 == NULL) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could not allocate b64 buffer.");
+    goto out;
+  }
+
+  if ((n_len = b64_pton(key, (u_char *)key_b64, k_len)) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could encode buffer b64.");
+    goto out;
+  }
+
+  // Invalid key (?)
+  if (n_len <= 4) {
+    goto out;
+  }
+
+  if (sshca_get_string(&key_b64, &n_len, &type, &t_len) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could not get cert's type string.");
+    goto out;
+  }
+
+  impl = sshca_get_implementation(type);
+  if (impl == NULL) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Invalid cert type: %s.", type);
+    goto out;
+  }
+
+  // Skip nonce for all types of certificates.
+  if (sshca_get_string(&key_b64, &n_len, NULL, NULL) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to skip cert's \"nonce\" field.");
+    goto out;
+  }
+
+  // Skip type specific fields.
+  if (impl->skip_custom_fields(&key_b64, &n_len) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to skip cert's custom/specific fields.");
+    goto out;
+  }
+
+  // Skip serial.
+  SKIP_UINT64(key_b64, n_len);
+
+  // Skip type.
+  SKIP_UINT32(key_b64, n_len);
+
+  // Skip key id.
+  if (sshca_get_string(&key_b64, &n_len, NULL, NULL) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to skip cert's \"key id\" field.");
+    goto out;
+  }
+
+  // Skip valid principals.
+  if (sshca_get_string(&key_b64, &n_len, NULL, NULL) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to skip cert's \"valid principals\" "
+               "field.");
+    goto out;
+  }
+
+  // Skip valid after.
+  SKIP_UINT64(key_b64, n_len);
+
+  // Skip valid before.
+  SKIP_UINT64(key_b64, n_len);
+
+  // Skip critical options.
+  if (sshca_get_string(&key_b64, &n_len, NULL, NULL) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to skip cert's \"critical options\" "
+               "field.");
+    goto out;
+  }
+
+  // Get extensions buffer.
+  if (sshca_get_string(&key_b64, &n_len, &tmp_exts, &tmp_exts_len) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to get cert's \"extensions\" field.");
+    goto out;
+  }
+
+  // The field extensions is a self described/sized buffer.
+  tmp_head = tmp_exts;
+  if (sshca_get_string(&tmp_exts, &tmp_exts_len, exts, &ret) < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Failed to read google's extension.");
+    goto out;
+  }
+
+out:
+  free(tmp_head);
+  free(type);
+  free(head);
+
+  return ret;
+}
+
+static size_t
+sshca_split_key(const char *blob, char **out) {
+  int i, len, k_start;
+  char *key = NULL;
+
+  len = 0;
+  k_start = 0;
+
+  for (i = 0; blob[i] != '\0'; i++) {
+    if (blob[i] == ' ' && key == NULL) {
+      k_start = i + 1;
+      key = (char *)blob + i + 1;
+    } else if (blob[i] == ' ' && key != NULL) {
+      len = i;
+    }
+  }
+
+  *out = strndup(key, len - k_start);
+  return len;
+}
+
+static size_t
+sshca_extract_fingerprint(const char *extension, char **out) {
+  int i = 0;
+
+  if (extension == NULL || strstr(extension, "fingerpr...@google.com=") == 
NULL) {
+    return 0;
+  }
+
+  for (i = 0; extension[i] != '\0'; i++) {
+    if (extension[i] == '=') {
+      *out = strdup(extension + i + 1);
+    }
+  }
+
+  return i;
+}
+
+int
+sshca_get_byoid_fingerprint(pam_handle_t *pamh, const char *blob, char 
**fingerprint) {
+  size_t f_len, k_len, exts_len = -1;
+  char *key, *exts = NULL;
+
+  k_len = sshca_split_key(blob, &key);
+  if (k_len <= 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could not split ssh ca cert.");
+    goto out;
+  }
+
+  exts_len = sshca_get_extension(pamh, key, k_len, &exts);
+  if (exts_len < 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could not parse/extract extension"
+               "from ssh ca cert.");
+    goto out;
+  }
+
+  f_len = sshca_extract_fingerprint(exts, fingerprint);
+  if (f_len == 0) {
+    PAM_SYSLOG(pamh, LOG_ERR, "Could not parse/extract fingerprint"
+               "from ssh ca cert's extension.");
+    goto out;
+  }
+
+out:
+  free(exts);
+  free(key);
+
+  return f_len;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-oslogin-20230502.00/src/pam/pam_oslogin_admin.cc 
new/guest-oslogin-20230808.00/src/pam/pam_oslogin_admin.cc
--- old/guest-oslogin-20230502.00/src/pam/pam_oslogin_admin.cc  2023-05-02 
20:42:44.000000000 +0200
+++ new/guest-oslogin-20230808.00/src/pam/pam_oslogin_admin.cc  2023-08-08 
20:00:56.000000000 +0200
@@ -27,6 +27,7 @@
 
 #include <compat.h>
 #include <oslogin_utils.h>
+#include <oslogin_sshca.h>
 
 using std::string;
 
@@ -48,7 +49,8 @@
   // The return value for this module should generally be ignored. By default 
we
   // will return PAM_SUCCESS.
   int pam_result = PAM_SUCCESS;
-  const char *user_name;
+  const char *user_name, *ssh_auth_info;
+  char *fingerprint = NULL;
 
   if ((pam_result = pam_get_user(pamh, &user_name, NULL)) != PAM_SUCCESS) {
     PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
@@ -74,6 +76,17 @@
   url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
       << "&policy=adminLogin";
 
+  ssh_auth_info = pam_getenv(pamh, "SSH_AUTH_INFO_0");
+  if (ssh_auth_info != NULL && strlen(ssh_auth_info) > 0) {
+    size_t fp_len = sshca_get_byoid_fingerprint(pamh, ssh_auth_info, 
&fingerprint);
+    // Don't try to add fingerprint parameter to policy call if we don't find 
it
+    // in the certificate.
+    if (fp_len > 0) {
+      url << "&fingerprint=" << fingerprint;
+      free(fingerprint);
+    }
+  }
+
   string filename = kSudoersDir;
   filename.append(user_name);
   struct stat buffer;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-oslogin-20230502.00/src/pam/pam_oslogin_login.cc 
new/guest-oslogin-20230808.00/src/pam/pam_oslogin_login.cc
--- old/guest-oslogin-20230502.00/src/pam/pam_oslogin_login.cc  2023-05-02 
20:42:44.000000000 +0200
+++ new/guest-oslogin-20230808.00/src/pam/pam_oslogin_login.cc  2023-08-08 
20:00:56.000000000 +0200
@@ -28,6 +28,7 @@
 
 #include <compat.h>
 #include <oslogin_utils.h>
+#include <oslogin_sshca.h>
 
 using oslogin_utils::ContinueSession;
 using oslogin_utils::GetUser;
@@ -48,7 +49,8 @@
 
 PAM_EXTERN int
 pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) {
-  const char *user_name;
+  const char *user_name, *ssh_auth_info;
+  char *fingerprint = NULL;
 
   if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
     PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
@@ -96,6 +98,17 @@
   url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
       << "&policy=login";
 
+  ssh_auth_info = pam_getenv(pamh, "SSH_AUTH_INFO_0");
+  if (ssh_auth_info != NULL && strlen(ssh_auth_info) > 0) {
+    size_t fp_len = sshca_get_byoid_fingerprint(pamh, ssh_auth_info, 
&fingerprint);
+    // Don't try to add fingerprint parameter to policy call if we don't find 
it
+    // in the certificate.
+    if (fp_len > 0) {
+      url << "&fingerprint=" << fingerprint;
+      free(fingerprint);
+    }
+  }
+
   if (!HttpGet(url.str(), &response, &http_code)) {
     PAM_SYSLOG(pamh, LOG_INFO, "Failed to validate organization user %s "
                                "has login permission.", user_name);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-oslogin-20230502.00/test/Makefile 
new/guest-oslogin-20230808.00/test/Makefile
--- old/guest-oslogin-20230502.00/test/Makefile 2023-05-02 20:42:44.000000000 
+0200
+++ new/guest-oslogin-20230808.00/test/Makefile 2023-08-08 20:00:56.000000000 
+0200
@@ -6,6 +6,7 @@
 
 TEST_RUNNER = ./test_runner --gtest_output=xml
 NEW_TEST_RUNNER = ./new_test_runner --gtest_output=xml
+SSHCA_TEST_RUNNER = ./sshca_runner --gtest_output=xml 
--gtest_filter="SSHCATests.*"
 CPPFLAGS += -I$(TOPDIR)/src/include -I/usr/include/json-c -I$(GTEST_DIR) 
-isystem $(GTEST_DIR)/include
 CXXFLAGS += -g -Wall -Wextra -std=c++11
 LDLIBS = -lcurl -ljson-c -lpthread
@@ -25,6 +26,12 @@
 test_runner: oslogin_utils_test.o $(TOPDIR)/src/oslogin_utils.o gtest-all.o
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
 
+sshca_runner: oslogin_sshca_test.o gtest-all.o 
$(TOPDIR)/src/pam/oslogin_sshca.o
+       $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) -lpam
+
+sshca_tests: sshca_runner
+       $(SSHCA_TEST_RUNNER)
+
 new_test_runner: oslogin_test.o gtest-all.o
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-oslogin-20230502.00/test/oslogin_sshca_test.cc 
new/guest-oslogin-20230808.00/test/oslogin_sshca_test.cc
--- old/guest-oslogin-20230502.00/test/oslogin_sshca_test.cc    1970-01-01 
01:00:00.000000000 +0100
+++ new/guest-oslogin-20230808.00/test/oslogin_sshca_test.cc    2023-08-08 
20:00:56.000000000 +0200
@@ -0,0 +1,273 @@
+// Copyright 2023 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <errno.h>
+#include <gtest/gtest.h>
+#include <oslogin_sshca.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+using std::string;
+using std::vector;
+
+namespace oslogin_utils {
+
+#define VALID_ECDSA_SINGLE_EXT "ecdsa-sha2-nistp256-cert-...@openssh.com " \
+  "AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg1yMhf" \
+  "NVBe4etWEQNDmtxhsAD+YAb7fl/Bn0Z+GGEE9EAAAAIbmlzdHAyNTYAAABBBJ+nM2cR4B" \
+  "FHbmokUIScpTaSkx/F1QS2KfIx6z4wcpUmjzKtbP0KFw12mMUiNHzlNBD0B2RnX54uN+k" \
+  "bjYGUdSAAAAAAAAAAAAAAAAEAAAAScGFudGhlb24uc2l0YXIubWlnAAAAFgAAABJwYW50" \
+  "aGVvbi5zaXRhci5taWcAAAAAAAAAAP//////////AAAAAAAAAEMAAAA7ZmluZ2VycHJpb" \
+  "nRAZ29vZ2xlLmNvbT1iODZkYjRjYS0wOWZkLTQyOWUtYjEyMS1hMTI3OTk2MTQwMzIAAA" \
+  "AAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAKgQiEGiszewwIeTPZv1/wwQF7K" \
+  "JeStkko6w7tcUXRUFWc1ajBUXjEQAxv64JSC+RvlFn7NTVxwzHb+lnbU9+74xfLKB9pqb" \
+  "XwiO8HNr4OhLdqfn6x8alfUwsezJzhdBs86o9B9YTFwX2UMJ0c3rZ/0Do6V3WlckMFiPh" \
+  "ZiXyiW3pYve+7kj9EZ/WJMAdxTnLPNF03azy3+siyVOWL2zkL8DVscpVVQ51ln15mwvI4" \
+  "/e0BVQbP0rtfGIjVOaUM4PyLAfTwg/GPpXroNefvRaxF1scXIjxVQTgm7EauWUyl0i4A1" \
+  "sQVEoXWyxQsgdGd6+BTZ3khJCAVSnLTeIhvP9utGJhSLvuJFZu1S1oA1s1/pvpDE9Nfc1" \
+  "QT14pWKGUU05Z8yPuBSwbbPqQZvSBhCsVNC5wN6AEkiIsKRJkcSXZIqGQpY9CUAJi9GxS" \
+  "R7ATiSy9GAJypHkHNDmJeBEfxYk7Z7jWBZ39HikmAaUfPYzpfjc0nPxYMkMKKy5wnftia" \
+  "pVxwAAAZQAAAAMcnNhLXNoYTItNTEyAAABgA4z6rSDNPKG9ae/C11q0U1CsPscK8tXFuK" \
+  "surZNXnfAbNwPp8/7x5pamgq5119PnAacll29U9+L+dYwmU8NsJgd1nnQPXh2hLdGs828" \
+  "hMOxSgwj35YSzToSulwmOxG7uOYI056WBc3ZZtcxBqvHThLAo6J2TnURicNMvID42ofqQ" \
+  "H2Wgozg1AOyHwCDdkrG304NoSfx76tIf/RjLu7yedhhu1x0hbz4DsLLKlm5vVI8jQvLB7" \
+  "iz37LMdvftX+Zqnf2EWDT7GspchbrCStH15GXaMCXwyObbDmKkYLz77XckBAQLjm0C6f2" \
+  "+f8UxtWzZDvqVFr/iIpivaRUhpGMYNED43XAKR/8uAMKA9d7mB8lD9wMBmRxbG4qDTM4q" \
+  "7Q539h7IPMoTRN82VL0v1KPVW8uWqqSjVFdrr2DshitTALMwXpf4VIxw/XuOV5ALNTCan" \
+  "bcetrgglFiujUFlIdxkHMmsIxHM88wEnJAlETd7zl9WR/FgQYn3y2dZz9VKoheJdg== "  \
+  "pantheon.sitar.mig"                                                    \
+
+#define INVALID_ECDSA_NO_FP "ecdsa-sha2-nistp256-cert-...@openssh.com A" \
+  "AAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgxlbtL" \
+  "/mjYXEgsXjl7GZgpvIFncxbfmjPYVewm1sdXo4AAAAIbmlzdHAyNTYAAABBBMYdGLr6M" \
+  "102qgBeJ3CanDi0WV1vGif2jMMv1ldtN0+wbDztYdtUu8iop/tN46wFVbfmSzyx/R2YL" \
+  "bvQ+z2k/sYAAAAAAAAAAAAAAAEAAAAWZmluZ2VycHJpbnRAZ29vZ2xlLmNvbQAAABoAA" \
+  "AAWZmluZ2VycHJpbnRAZ29vZ2xlLmNvbQAAAABk0UUMAAAAAGaxJ2gAAAAAAAAAAAAAA" \
+  "AAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPoCTDKl0" \
+  "jZG3V2P14+PDbYrD0sDBsKwYaZEn85tM6mmGEY1yHg/VI76O27xTqE56PJECph1eKmo4" \
+  "YA/ch8wwewAAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIQCN6KRgSVKYH" \
+  "pM3dlil8jDXlpL4U1JSmP3MeHX0OKcpHgAAACAYiWa3KrreEzN+VrnuhwStH70bvH9Qm" \
+  "6Va6a0IcMrMkA== fingerpr...@google.com"                               \
+
+#define INVALID_ECDSA_NON_CERT "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTI" \
+  "tbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMYdGLr6M102qgBeJ3CanDi0WV1vGif2jMM" \
+  "v1ldtN0+wbDztYdtUu8iop/tN46wFVbfmSzyx/R2YLbvQ+z2k/sY= "               \
+  "fingerpr...@google.com"                                               \
+
+#define VALID_RSA_SINGLE_EXT "ssh-rsa-cert-...@openssh.com AAAAHHNzaC1yc" \
+  "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" \
+  "GqmJpNjwsqExxW5E= fingerpr...@google.com"                              \
+
+#define INVALID_RSA_NO_FP "ssh-rsa-cert-...@openssh.com AAAAHHNzaC1yc2Et" \
+  "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 "     \
+  "fingerpr...@google.com"                                                \
+
+#define INVALID_RSA_NON_CERT "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCU/m" \
+  "ydd9mSwlSDv4T3OiL5IHrvSuXpWFvCEDmVyLxBHz1FCwjnk3G5xSt9nGtUyL0KpGt0dyv" \
+  "LU07JGB33cbVnVe1z3373FNKxF8LdwDTEZG6xijXuOi4xfk47arlpk9Pw14qcnVu9on4R" \
+  "m4cSmm5PkyIwTfJsKvOl8oOgZ0HZG7pzYEt+9wUoeGzUE0rsAreNFVB7ZBqHp2ZtdIe5d" \
+  "dbarKAl1JKZuz8EbUmdjBYXsMYLHd0gUd+rvHyaw7p3iJyESaJcqUOQHrecpkLqWiN+TU" \
+  "NZPchE/T19LSP/fQbPCGmqc+mC6YodSEbLkO6JmOaW+knTEc9D6xdozx6Oa4vR "       \
+  "fingerpr...@google.com"                                                \
+
+#define VALID_DSA_SINGLE_EXT "ssh-dss-cert-...@openssh.com AAAAHHNzaC1kc" \
+  "3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgH400e9SzsvaN8OkKvH26sXEJtU/BVc2IBG" \
+  "fdZDHk508AAACBAO9UdOmq7Z0qy86mwsDf07TmXQe7X0TLKbyFSsd2b+jTCzpXy9rBhgg" \
+  "oJlzYzxSQgtR4JaSTauZMiQQViN3cKvHuGfAXIOIMtMHVupNy6WSkcixGrvw6Y0Yr90+e" \
+  "8PXcFw6jwQbFZX4v9zlUuIl067rCrxp1jnhBjxvBZEmpR/ezAAAAFQCO10V2wYXJ7cSo4" \
+  "eEgHB1BnOxbzwAAAIEAzbdt5bgzV164ljY6dimHUUnKUnYEq7VY3gJZSN3YGwMHnIYw94" \
+  "gtNxkhP09SkPn+llAH/NTKq2beu9GizybqIc9Gtfh3AGqYLyWhePZumcUYYShMc7eNUfN" \
+  "RDp1QtWnX/A/HvVsNEdqHW3R9cq5miEWgoUFHOHhLZtUOk1wbJe4AAACAITYKkJACQAoh" \
+  "b9q1Ehxea8qoYaM2ctI3JCN59bbcgP1Tngaq2TcJOup0+AVN5P7ILQGh3s9xngdcQU9RJ" \
+  "XlUh6yHpW0BwkAOAKjX7ASjx4rKOkN0PeT2KtyGWqLcnbFRSQGNQOs+vv3TIUofZosXKT" \
+  "A2EtmjpKcIbfu3lF+J50gAAAAAAAAAAAAAAAEAAAAWZmluZ2VycHJpbnRAZ29vZ2xlLmN" \
+  "vbQAAABoAAAAWZmluZ2VycHJpbnRAZ29vZ2xlLmNvbQAAAABk0SkoAAAAAGaxC5IAAAAA" \
+  "AAAAQwAAADtmaW5nZXJwcmludEBnb29nbGUuY29tPWI4NmRiNGNhLTA5ZmQtNDI5ZS1iM" \
+  "TIxLWExMjc5OTYxNDAzMgAAAAAAAAAAAAABsgAAAAdzc2gtZHNzAAAAgQC1WfAI4qlV3J" \
+  "jY+tsHhQEVJgMVPzrNa94pvSDRc9FYexYHaky6e0zroP8LmxTEZyOzfT9H22lqmIPRHXp" \
+  "dEB5ge7FAO7/QsavsAUQHnpiyaqng4ojgPTQJzY0tuYUkV9a265gZJpqdY0wNLcSJtDFk" \
+  "WtixpTSswF1gGs5maq5ljQAAABUAlYIrD8mImqdRNg7FizxOscWV8WUAAACBAJE9UuRok" \
+  "fqK1ZodxfX0Me1NgS+4rpH9iWqHudpQiR134OUT3w29dtTDKdDjesuOyEDGi17Z5Honsv" \
+  "yktNVzel+F8q6/24NI4VSBnRXi8TkXvK6BjRFJsnVJRMiF8zErd3ihWDmsEXcMJ0X/uQw" \
+  "tBKREhGri3xz1bVVH+Iwb8F5SAAAAgFtqHHk0TP8wLmggYh+i9FDhN+99yt7FxDAGg4di" \
+  "JDkpmo8MUaXmxibghK0c15Tta9hoOUqtArpYdBm0WyfEM/5Us2qVVcJp4Cjrw9OJ3lEgj" \
+  "+OSizEVlMEujCFT/j032c5Y4O3ScCEUDrFjlutMtlUfvPaDGX7yH0mYONAb6p2FAAAANw" \
+  "AAAAdzc2gtZHNzAAAAKH5faM5YTlMn+h2cf99PJ8rjvqQUJoh5yi3a4pkGcr5MJs53Wfi" \
+  "DPaA= fingerpr...@google.com"                                          \
+
+#define INVALID_DSA_NO_FP "ssh-dss-cert-...@openssh.com AAAAHHNzaC1kc3Mt" \
+  "Y2VydC12MDFAb3BlbnNzaC5jb20AAAAgGrlYnOqQxs/zzfWRcrM7DHrFy653/x7rtOghw" \
+  "R/f3HIAAACBALzWA8yWLownZsO4Tuc4DF6EplCJ1SBSEqMYAEhzrnxjHkoOpJ3Ncs+Zn5" \
+  "jdcnCamkm6KQ4keXkV0xwLthRgLxhUguc9xANV5k2Vft+axWr+cp+KNiGzDjblTUnWzQD" \
+  "5Q/mBpiFKL7EiZski3swpJQs0kGQW2hxbjlr7I0EhM8e1AAAAFQDdVQaUxoK58jpTFdVi" \
+  "gI3yzjtK3wAAAIB1Z8nZ4QEaqSLK5+Xm2LAbn32Do0nGtOkPCWYjZzlcfHt1Hb7gCIe5X" \
+  "gqPZM3hYWuOisKsk2gxxeVyiX6VBuYpCbINduxw8h/7nMyOTFLr01Y282/eHq20XHPLD2" \
+  "2hdY1l44de8EhYrcHRPM7twnFJU0X7og6QNdOnvMXQ+WclWwAAAIAmJmVahDp1Vu22M9t" \
+  "7V4yRYP8Wh3ROletzPrY9kpgTR5QtfZ57QPxN3n2r61iLaPWR0cQ12x4LviBVTsFk87oE" \
+  "9SAxzcDPwyzbSM3ATIzI6TauIVacVFoUdeAy2rjaLUGYcdD745oudXmyXq1VupLHaJC9k" \
+  "ePm8hkeZyf/5F6XBwAAAAAAAAAAAAAAAQAAABZmaW5nZXJwcmludEBnb29nbGUuY29tAA" \
+  "AAGgAAABZmaW5nZXJwcmludEBnb29nbGUuY29tAAAAAGTRQFwAAAAAZrEiogAAAAAAAAA" \
+  "AAAAAAAAAAbEAAAAHc3NoLWRzcwAAAIEA4FZIvoI2syNIyZ34DibfH4Pm3Rf0iKHUIgLR" \
+  "+izM/aP9jDAXRD/c2Tl2cnw4pVJdun2+ByBNkRHQJ+86dMVXhvpIPjoeK4dqJsEBsSj7L" \
+  "ohXMJtdn5LyBpiiyZ4jq7uVeWGm1q7Lh6WeIuBVNLgwoE1/z5RtScGhbHBPb8q7RbcAAA" \
+  "AVAOHoBqU7wxf09lWcarL6SaOAyWJ5AAAAgGLb9fIGSP50+sfKqxSohCU23B3SYCIf7QI" \
+  "1Zjql9FeDY9AfvkzVaiJvA/eoZKwGhG5FbDtA9eyuCfiB5E6VqaShx3Mp3yCKPOaCznrv" \
+  "LKJsqMKC7ReU2obugmMELRmbTdZdQCdvvNrVjqvW54aUIzF4zC9ZKeiKtG6MQ7VP/MrRA" \
+  "AAAgGk5pXHfmjL8vDZIwtWhxm3gdN5TubyKgW1i/nIMDgLhLqLw4//NY86wkGj84MwniT" \
+  "Gf2pB8lGzBPj+ByQIMABe/iMq9uRXLNUFta7PYQKi3UjCoCwv0p88advtwOXRyHu1THxr" \
+  "JDMmmDirJnSYW8I7F9gY4UMldYwy9dyNqwfoQAAAANwAAAAdzc2gtZHNzAAAAKAnb/pHN" \
+  "+YzrU7BOR7qnGs1qJqWhgFKXETMeHxPzpi4ny9tSNlI6c0g= "                     \
+  "fingerpr...@google.com"                                                \
+
+#define INVALID_DSA_NON_CERT "ssh-dss AAAAB3NzaC1kc3MAAACBAO9UdOmq7Z0qy8" \
+  "6mwsDf07TmXQe7X0TLKbyFSsd2b+jTCzpXy9rBhggoJlzYzxSQgtR4JaSTauZMiQQViN3" \
+  "cKvHuGfAXIOIMtMHVupNy6WSkcixGrvw6Y0Yr90+e8PXcFw6jwQbFZX4v9zlUuIl067rC" \
+  "rxp1jnhBjxvBZEmpR/ezAAAAFQCO10V2wYXJ7cSo4eEgHB1BnOxbzwAAAIEAzbdt5bgzV" \
+  "164ljY6dimHUUnKUnYEq7VY3gJZSN3YGwMHnIYw94gtNxkhP09SkPn+llAH/NTKq2beu9" \
+  "GizybqIc9Gtfh3AGqYLyWhePZumcUYYShMc7eNUfNRDp1QtWnX/A/HvVsNEdqHW3R9cq5" \
+  "miEWgoUFHOHhLZtUOk1wbJe4AAACAITYKkJACQAohb9q1Ehxea8qoYaM2ctI3JCN59bbc" \
+  "gP1Tngaq2TcJOup0+AVN5P7ILQGh3s9xngdcQU9RJXlUh6yHpW0BwkAOAKjX7ASjx4rKO" \
+  "kN0PeT2KtyGWqLcnbFRSQGNQOs+vv3TIUofZosXKTA2EtmjpKcIbfu3lF+J50g= "      \
+  "fingerpr...@google.com"                                                \
+
+#define VALID_ED25519_SINGLE_EXT "ssh-ed25519-cert-...@openssh.com AAAAI" \
+  "HNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDaErnQWEw/jxPD0JUJsEk" \
+  "CtENcE11Zl53QHbxbAgx22AAAAIHs6r2AekiTHmmoJMKxAKtKW4qcGq5Ku1+SJ1NLdZh0" \
+  "1AAAAAAAAAAAAAAABAAAAFmZpbmdlcnByaW50QGdvb2dsZS5jb20AAAAaAAAAFmZpbmdl" \
+  "cnByaW50QGdvb2dsZS5jb20AAAAAZNEqzAAAAABmsQ0IAAAAAAAAAEMAAAA7ZmluZ2Vyc" \
+  "HJpbnRAZ29vZ2xlLmNvbT1iODZkYjRjYS0wOWZkLTQyOWUtYjEyMS1hMTI3OTk2MTQwMz" \
+  "IAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgyxEJdP6tUhJY3J/4bgLpzyUojE9" \
+  "6YKzE2t/RAx5l32kAAABTAAAAC3NzaC1lZDI1NTE5AAAAQNEBsSEvp5tVMbKUsjIZ0jEa" \
+  "Yv0T0U/GZoCiLfVm3pcXV3RA8aze+y/pbjv+MOxjmAb4KbRH31/S34UALsyGwQM= fing" \
+  "erpr...@google.com"                                                    \
+
+#define INVALID_ED25519_NO_FP "ssh-ed25519-cert-...@openssh.com AAAAIHNz" \
+  "aC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDDgIXa9QLFY7RpSNnWDm3Saq" \
+  "YZ5HGcpzHq9hdv64nqXAAAAIKfDRdZjpCb2YVsmhs286hQTH7JFctizNC0W7UQKfruSAA" \
+  "AAAAAAAAAAAAABAAAAFmZpbmdlcnByaW50QGdvb2dsZS5jb20AAAAaAAAAFmZpbmdlcnB" \
+  "yaW50QGdvb2dsZS5jb20AAAAAZNFCeAAAAABmsSTsAAAAAAAAAAAAAAAAAAAAMwAAAAtz" \
+  "c2gtZWQyNTUxOQAAACBTEPiuWCgwX9JhFzMNLex4d9uRtdWfUg0OCAdH6nVbsAAAAFMAA" \
+  "AALc3NoLWVkMjU1MTkAAABAt2CPRZos3Lna+44LwI6ON8rRktxAqz1S4nUf+IwrG83Wbv" \
+  "nEvvZ2plHLTAU7GP2ZMedVKoXB9KXB2vNBVjt9Cg== fingerpr...@google.com"     \
+
+#define INVALID_ED25519_NON_CERT "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH" \
+  "s6r2AekiTHmmoJMKxAKtKW4qcGq5Ku1+SJ1NLdZh01 fingerpr...@google.com"     \
+
+TEST(SSHCATests, TestValidSingleExtCert) {
+  struct {
+    const char *key;
+  } *iter, tests[] = {
+    {VALID_RSA_SINGLE_EXT},
+    {VALID_DSA_SINGLE_EXT},
+    {VALID_ECDSA_SINGLE_EXT},
+    {VALID_ED25519_SINGLE_EXT},
+    { NULL },
+  };
+
+  for (iter = tests; iter->key != NULL; iter++) {
+    char *fingerprint = NULL;
+    size_t len = sshca_get_byoid_fingerprint(NULL, iter->key, &fingerprint);
+    ASSERT_GT(len, 0);
+    ASSERT_STREQ(fingerprint, "b86db4ca-09fd-429e-b121-a12799614032");
+    free(fingerprint);
+  }
+}
+
+TEST(SSHCATests, TestInvalidNoFpCert) {
+  struct {
+    const char *key;
+  } *iter, tests[] = {
+    {INVALID_DSA_NO_FP},
+    {INVALID_DSA_NON_CERT},
+    {INVALID_ED25519_NO_FP},
+    {INVALID_ED25519_NON_CERT},
+    {INVALID_RSA_NO_FP},
+    {INVALID_RSA_NON_CERT},
+    {INVALID_ECDSA_NO_FP},
+    {INVALID_ECDSA_NON_CERT},
+    { NULL },
+  };
+
+  for (iter = tests; iter->key != NULL; iter++) {
+    char *fingerprint = NULL;
+    size_t len = sshca_get_byoid_fingerprint(NULL, iter->key, &fingerprint);
+    ASSERT_EQ(len, 0);
+    ASSERT_STREQ(fingerprint, NULL);
+    free(fingerprint);
+  }
+}
+
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-oslogin-20230502.00/third_party/include/openbsd.h 
new/guest-oslogin-20230808.00/third_party/include/openbsd.h
--- old/guest-oslogin-20230502.00/third_party/include/openbsd.h 1970-01-01 
01:00:00.000000000 +0100
+++ new/guest-oslogin-20230808.00/third_party/include/openbsd.h 2023-08-08 
20:00:56.000000000 +0200
@@ -0,0 +1,242 @@
+/*     $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
+
+#ifndef _OPENBSD_H_
+#define _OPENBSD_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 24-bit groups of input bits as output
+   strings of 4 encoded characters. Proceeding from left to right, a
+   24-bit input group is formed by concatenating 3 8-bit input groups.
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+   of which is translated into a single digit in the base64 alphabet.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                     
  
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+int
+b64_pton(char const *src, u_char *target, size_t targsize)
+{
+       u_int tarindex, state;
+       int ch;
+       char *pos;
+
+       state = 0;
+       tarindex = 0;
+
+       while ((ch = *src++) != '\0') {
+               if (isspace(ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad64)
+                       break;
+
+               pos = strchr(Base64, ch);
+               if (pos == 0)           /* A non-base64 character. */
+                       return (-1);
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] = (pos - Base64) << 2;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 4;
+                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
+                                                       << 4 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 2;
+                               target[tarindex+1]  = ((pos - Base64) & 0x03)
+                                                       << 6;
+                       }
+                       tarindex++;
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] |= (pos - Base64);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               }
+       }
+
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad64) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-1);
+
+               case 2:         /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for (; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad64)
+                               return (-1);
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 3:         /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for (; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       return (-1);
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0)
+                               return (-1);
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-1);
+       }
+
+       return (tarindex);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Reply via email to