summaryrefslogtreecommitdiffstats
path: root/net/rxrpc
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-04-06 05:11:59 -0400
committerDavid Howells <dhowells@redhat.com>2017-04-06 05:11:59 -0400
commitef68622da9cc0c4e5202f90093a3a5314e41e9e9 (patch)
treee1fe504e4a3a217a248689dd28e12f1926b21ad0 /net/rxrpc
parent84a4c09c38903a92ba670375efea5165949a465b (diff)
rxrpc: Handle temporary errors better in rxkad security
In the rxkad security module, when we encounter a temporary error (such as ENOMEM) from which we could conceivably recover, don't abort the connection, but rather permit retransmission of the relevant packets to induce a retry. Note that I'm leaving some places that could be merged together to insert tracing in the next patch. Signed-off-by; David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc')
-rw-r--r--net/rxrpc/rxkad.c78
1 files changed, 40 insertions, 38 deletions
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 2d5838a3dc24..988903f1dc80 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -759,16 +759,14 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
759 759
760 _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key)); 760 _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
761 761
762 if (!conn->params.key) { 762 abort_code = RX_PROTOCOL_ERROR;
763 _leave(" = -EPROTO [no key]"); 763 if (!conn->params.key)
764 return -EPROTO; 764 goto protocol_error;
765 }
766 765
766 abort_code = RXKADEXPIRED;
767 ret = key_validate(conn->params.key); 767 ret = key_validate(conn->params.key);
768 if (ret < 0) { 768 if (ret < 0)
769 *_abort_code = RXKADEXPIRED; 769 goto other_error;
770 return ret;
771 }
772 770
773 abort_code = RXKADPACKETSHORT; 771 abort_code = RXKADPACKETSHORT;
774 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 772 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
@@ -787,8 +785,9 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
787 goto protocol_error; 785 goto protocol_error;
788 786
789 abort_code = RXKADLEVELFAIL; 787 abort_code = RXKADLEVELFAIL;
788 ret = -EACCES;
790 if (conn->params.security_level < min_level) 789 if (conn->params.security_level < min_level)
791 goto protocol_error; 790 goto other_error;
792 791
793 token = conn->params.key->payload.data[0]; 792 token = conn->params.key->payload.data[0];
794 793
@@ -815,9 +814,10 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
815 return rxkad_send_response(conn, &sp->hdr, &resp, token->kad); 814 return rxkad_send_response(conn, &sp->hdr, &resp, token->kad);
816 815
817protocol_error: 816protocol_error:
817 ret = -EPROTO;
818other_error:
818 *_abort_code = abort_code; 819 *_abort_code = abort_code;
819 _leave(" = -EPROTO [%d]", abort_code); 820 return ret;
820 return -EPROTO;
821} 821}
822 822
823/* 823/*
@@ -848,10 +848,10 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
848 switch (ret) { 848 switch (ret) {
849 case -EKEYEXPIRED: 849 case -EKEYEXPIRED:
850 *_abort_code = RXKADEXPIRED; 850 *_abort_code = RXKADEXPIRED;
851 goto error; 851 goto other_error;
852 default: 852 default:
853 *_abort_code = RXKADNOAUTH; 853 *_abort_code = RXKADNOAUTH;
854 goto error; 854 goto other_error;
855 } 855 }
856 } 856 }
857 857
@@ -860,13 +860,11 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
860 860
861 memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv)); 861 memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
862 862
863 ret = -ENOMEM;
863 req = skcipher_request_alloc(conn->server_key->payload.data[0], 864 req = skcipher_request_alloc(conn->server_key->payload.data[0],
864 GFP_NOFS); 865 GFP_NOFS);
865 if (!req) { 866 if (!req)
866 *_abort_code = RXKADNOAUTH; 867 goto temporary_error;
867 ret = -ENOMEM;
868 goto error;
869 }
870 868
871 sg_init_one(&sg[0], ticket, ticket_len); 869 sg_init_one(&sg[0], ticket, ticket_len);
872 skcipher_request_set_callback(req, 0, NULL, NULL); 870 skcipher_request_set_callback(req, 0, NULL, NULL);
@@ -943,13 +941,13 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
943 if (issue > now) { 941 if (issue > now) {
944 *_abort_code = RXKADNOAUTH; 942 *_abort_code = RXKADNOAUTH;
945 ret = -EKEYREJECTED; 943 ret = -EKEYREJECTED;
946 goto error; 944 goto other_error;
947 } 945 }
948 946
949 if (issue < now - life) { 947 if (issue < now - life) {
950 *_abort_code = RXKADEXPIRED; 948 *_abort_code = RXKADEXPIRED;
951 ret = -EKEYEXPIRED; 949 ret = -EKEYEXPIRED;
952 goto error; 950 goto other_error;
953 } 951 }
954 952
955 *_expiry = issue + life; 953 *_expiry = issue + life;
@@ -961,16 +959,15 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
961 /* get the service instance name */ 959 /* get the service instance name */
962 name = Z(INST_SZ); 960 name = Z(INST_SZ);
963 _debug("KIV SINST: %s", name); 961 _debug("KIV SINST: %s", name);
964 962 return 0;
965 ret = 0;
966error:
967 _leave(" = %d", ret);
968 return ret;
969 963
970bad_ticket: 964bad_ticket:
971 *_abort_code = RXKADBADTICKET; 965 *_abort_code = RXKADBADTICKET;
972 ret = -EBADMSG; 966 ret = -EPROTO;
973 goto error; 967other_error:
968 return ret;
969temporary_error:
970 return ret;
974} 971}
975 972
976/* 973/*
@@ -1054,9 +1051,10 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
1054 goto protocol_error; 1051 goto protocol_error;
1055 1052
1056 /* extract the kerberos ticket and decrypt and decode it */ 1053 /* extract the kerberos ticket and decrypt and decode it */
1054 ret = -ENOMEM;
1057 ticket = kmalloc(ticket_len, GFP_NOFS); 1055 ticket = kmalloc(ticket_len, GFP_NOFS);
1058 if (!ticket) 1056 if (!ticket)
1059 return -ENOMEM; 1057 goto temporary_error;
1060 1058
1061 abort_code = RXKADPACKETSHORT; 1059 abort_code = RXKADPACKETSHORT;
1062 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 1060 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
@@ -1064,12 +1062,9 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
1064 goto protocol_error_free; 1062 goto protocol_error_free;
1065 1063
1066 ret = rxkad_decrypt_ticket(conn, ticket, ticket_len, &session_key, 1064 ret = rxkad_decrypt_ticket(conn, ticket, ticket_len, &session_key,
1067 &expiry, &abort_code); 1065 &expiry, _abort_code);
1068 if (ret < 0) { 1066 if (ret < 0)
1069 *_abort_code = abort_code; 1067 goto temporary_error_free;
1070 kfree(ticket);
1071 return ret;
1072 }
1073 1068
1074 /* use the session key from inside the ticket to decrypt the 1069 /* use the session key from inside the ticket to decrypt the
1075 * response */ 1070 * response */
@@ -1123,10 +1118,8 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
1123 * this the connection security can be handled in exactly the same way 1118 * this the connection security can be handled in exactly the same way
1124 * as for a client connection */ 1119 * as for a client connection */
1125 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno); 1120 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
1126 if (ret < 0) { 1121 if (ret < 0)
1127 kfree(ticket); 1122 goto temporary_error_free;
1128 return ret;
1129 }
1130 1123
1131 kfree(ticket); 1124 kfree(ticket);
1132 _leave(" = 0"); 1125 _leave(" = 0");
@@ -1140,6 +1133,15 @@ protocol_error:
1140 *_abort_code = abort_code; 1133 *_abort_code = abort_code;
1141 _leave(" = -EPROTO [%d]", abort_code); 1134 _leave(" = -EPROTO [%d]", abort_code);
1142 return -EPROTO; 1135 return -EPROTO;
1136
1137temporary_error_free:
1138 kfree(ticket);
1139temporary_error:
1140 /* Ignore the response packet if we got a temporary error such as
1141 * ENOMEM. We just want to send the challenge again. Note that we
1142 * also come out this way if the ticket decryption fails.
1143 */
1144 return ret;
1143} 1145}
1144 1146
1145/* 1147/*