summaryrefslogtreecommitdiff
path: root/sshsig.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-01-23 02:43:48 +0000
committerDamien Miller <djm@mindrot.org>2020-01-23 13:45:24 +1100
commit56cffcc09f8a2e661d2ba02e61364ae6f998b2b1 (patch)
tree7056f21f29a73cce790ed19c6118983f1ceb6c7d /sshsig.c
parent65cf8730de6876a56595eef296e07a86c52534a6 (diff)
upstream: add a new signature operations "find-principal" to look
up the principal associated with a signature from an allowed-signers file. Work by Sebastian Kinne; ok dtucker@ OpenBSD-Commit-ID: 6f782cc7e18e38fcfafa62af53246a1dcfe74e5d
Diffstat (limited to 'sshsig.c')
-rw-r--r--sshsig.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/sshsig.c b/sshsig.c
index 6d72f92f5..e9f4baa76 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -866,3 +866,120 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
866 free(line); 866 free(line);
867 return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; 867 return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r;
868} 868}
869
870static int
871get_matching_principal_from_line(const char *path, u_long linenum, char *line,
872 const struct sshkey *sign_key, char **principalsp)
873{
874 struct sshkey *found_key = NULL;
875 char *principals = NULL;
876 int r, found = 0;
877 const char *reason = NULL;
878 struct sshsigopt *sigopts = NULL;
879
880 if (principalsp != NULL)
881 *principalsp = NULL;
882
883 /* Parse the line */
884 if ((r = parse_principals_key_and_options(path, linenum, line,
885 NULL, &principals, &found_key, &sigopts)) != 0) {
886 /* error already logged */
887 goto done;
888 }
889
890 if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
891 /* Exact match of key */
892 debug("%s:%lu: matched key", path, linenum);
893 /* success */
894 found = 1;
895 } else if (sigopts->ca && sshkey_is_cert(sign_key) &&
896 sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
897 /* Match of certificate's CA key */
898 if ((r = sshkey_cert_check_authority(sign_key, 0, 1,
899 principals, &reason)) != 0) {
900 error("%s:%lu: certificate not authorized: %s",
901 path, linenum, reason);
902 goto done;
903 }
904 debug("%s:%lu: matched certificate CA key", path, linenum);
905 /* success */
906 found = 1;
907 } else {
908 /* Key didn't match */
909 goto done;
910 }
911 done:
912 if (found) {
913 *principalsp = principals;
914 principals = NULL; /* transferred */
915 }
916 free(principals);
917 sshkey_free(found_key);
918 sshsigopt_free(sigopts);
919 return found ? 0 : SSH_ERR_KEY_NOT_FOUND;
920}
921
922int
923sshsig_find_principal(const char *path, const struct sshkey *sign_key,
924 char **principal)
925{
926 FILE *f = NULL;
927 char *line = NULL;
928 size_t linesize = 0;
929 u_long linenum = 0;
930 int r, oerrno;
931
932 if ((f = fopen(path, "r")) == NULL) {
933 oerrno = errno;
934 error("Unable to open allowed keys file \"%s\": %s",
935 path, strerror(errno));
936 errno = oerrno;
937 return SSH_ERR_SYSTEM_ERROR;
938 }
939
940 while (getline(&line, &linesize, f) != -1) {
941 linenum++;
942 r = get_matching_principal_from_line(path, linenum, line,
943 sign_key, principal);
944 free(line);
945 line = NULL;
946 if (r == SSH_ERR_KEY_NOT_FOUND)
947 continue;
948 else if (r == 0) {
949 /* success */
950 fclose(f);
951 return 0;
952 } else
953 break;
954 }
955 free(line);
956 /* Either we hit an error parsing or we simply didn't find the key */
957 if (ferror(f) != 0) {
958 oerrno = errno;
959 fclose(f);
960 error("Unable to read allowed keys file \"%s\": %s",
961 path, strerror(errno));
962 errno = oerrno;
963 return SSH_ERR_SYSTEM_ERROR;
964 }
965 fclose(f);
966 return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r;
967}
968
969int
970sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey)
971{
972 struct sshkey *pk = NULL;
973 int r = SSH_ERR_SIGNATURE_INVALID;
974
975 if (pubkey != NULL)
976 *pubkey = NULL;
977 if ((r = sshsig_parse_preamble(signature)) != 0)
978 return r;
979 if ((r = sshkey_froms(signature, &pk)) != 0)
980 return r;
981
982 *pubkey = pk;
983 pk = NULL;
984 return 0;
985}