1070 }
1071 if (isrcext != NULL && idstext == NULL) {
1072 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
1073 return (EINVAL);
1074 }
1075 if (assoc == NULL) {
1076 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
1077 return (EINVAL);
1078 }
1079 if (key == NULL) {
1080 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_AKEY;
1081 return (EINVAL);
1082 }
1083
1084 src = (struct sockaddr_in *)(srcext + 1);
1085 dst = (struct sockaddr_in *)(dstext + 1);
1086
1087 /* Sundry ADD-specific reality checks. */
1088 /* XXX STATS : Logging/stats here? */
1089
1090 if ((assoc->sadb_sa_state != SADB_SASTATE_MATURE) &&
1091 (assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE_ELSEWHERE)) {
1092 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
1093 return (EINVAL);
1094 }
1095 if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1096 *diagnostic = SADB_X_DIAGNOSTIC_ENCR_NOTSUPP;
1097 return (EINVAL);
1098 }
1099 if (assoc->sadb_sa_flags & ~ahstack->ah_sadb.s_addflags) {
1100 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
1101 return (EINVAL);
1102 }
1103 if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0)
1104 return (EINVAL);
1105
1106 ASSERT(src->sin_family == dst->sin_family);
1107
1108 /* Stuff I don't support, for now. XXX Diagnostic? */
1109 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1110 return (EOPNOTSUPP);
1111
1149 mutex_exit(&ipss->ipsec_alg_lock);
1150 return (EINVAL);
1151 }
1152
1153 mutex_exit(&ipss->ipsec_alg_lock);
1154
1155 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1156 diagnostic, ahstack));
1157 }
1158
1159 /* Refactor me */
1160 /*
1161 * Update a security association. Updates come in two varieties. The first
1162 * is an update of lifetimes on a non-larval SA. The second is an update of
1163 * a larval SA, which ends up looking a lot more like an add.
1164 */
1165 static int
1166 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1167 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1168 {
1169 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1170 sadb_address_t *dstext =
1171 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1172 mblk_t *buf_pkt;
1173 int rcode;
1174
1175 if (dstext == NULL) {
1176 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
1177 return (EINVAL);
1178 }
1179
1180 rcode = sadb_update_sa(mp, ksi, &buf_pkt, &ahstack->ah_sadb,
1181 diagnostic, ahstack->ah_pfkey_q, ah_add_sa,
1182 ahstack->ipsecah_netstack, sadb_msg_type);
1183
1184 if ((assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE) ||
1185 (rcode != 0)) {
1186 return (rcode);
1187 }
1188
1189 HANDLE_BUF_PKT(ah_taskq, ahstack->ipsecah_netstack->netstack_ipsec,
1190 ahstack->ah_dropper, buf_pkt);
1191
1192 return (rcode);
1193 }
1194
1195 /* Refactor me */
1196 /*
1197 * Delete a security association. This is REALLY likely to be code common to
1198 * both AH and ESP. Find the association, then unlink it.
1199 */
1200 static int
1201 ah_del_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1202 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1203 {
1204 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1205 sadb_address_t *dstext =
1206 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1207 sadb_address_t *srcext =
1208 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
1209 struct sockaddr_in *sin;
1210
1211 if (assoc == NULL) {
1212 if (dstext != NULL)
1319 * AF_INET.
1320 */
1321 if (!sadb_addrfix(ksi, ahstack->ah_pfkey_q, mp,
1322 ahstack->ipsecah_netstack) ||
1323 ah_pfkey_reality_failures(mp, ksi, ahstack)) {
1324 return;
1325 }
1326
1327 switch (samsg->sadb_msg_type) {
1328 case SADB_ADD:
1329 error = ah_add_sa(mp, ksi, &diagnostic,
1330 ahstack->ipsecah_netstack);
1331 if (error != 0) {
1332 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1333 diagnostic, ksi->ks_in_serial);
1334 }
1335 /* else ah_add_sa() took care of things. */
1336 break;
1337 case SADB_DELETE:
1338 case SADB_X_DELPAIR:
1339 case SADB_X_DELPAIR_STATE:
1340 error = ah_del_sa(mp, ksi, &diagnostic, ahstack,
1341 samsg->sadb_msg_type);
1342 if (error != 0) {
1343 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1344 diagnostic, ksi->ks_in_serial);
1345 }
1346 /* Else ah_del_sa() took care of things. */
1347 break;
1348 case SADB_GET:
1349 error = sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, &diagnostic,
1350 ahstack->ah_pfkey_q, samsg->sadb_msg_type);
1351 if (error != 0) {
1352 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1353 diagnostic, ksi->ks_in_serial);
1354 }
1355 /* Else sadb_get_sa() took care of things. */
1356 break;
1357 case SADB_FLUSH:
1358 sadbp_flush(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
1359 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, samsg, ksi, NULL);
1893
1894 /* Refactor me */
1895 /*
1896 * Handle the SADB_GETSPI message. Create a larval SA.
1897 */
1898 static void
1899 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1900 {
1901 ipsa_t *newbie, *target;
1902 isaf_t *outbound, *inbound;
1903 int rc, diagnostic;
1904 sadb_sa_t *assoc;
1905 keysock_out_t *kso;
1906 uint32_t newspi;
1907
1908 /*
1909 * Randomly generate a proposed SPI value.
1910 */
1911 (void) random_get_pseudo_bytes((uint8_t *)&newspi, sizeof (uint32_t));
1912 newbie = sadb_getspi(ksi, newspi, &diagnostic,
1913 ahstack->ipsecah_netstack, IPPROTO_AH);
1914
1915 if (newbie == NULL) {
1916 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, diagnostic,
1917 ksi->ks_in_serial);
1918 return;
1919 } else if (newbie == (ipsa_t *)-1) {
1920 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, diagnostic,
1921 ksi->ks_in_serial);
1922 return;
1923 }
1924
1925 /*
1926 * XXX - We may randomly collide. We really should recover from this.
1927 * Unfortunately, that could require spending way-too-much-time
1928 * in here. For now, let the user retry.
1929 */
1930
1931 if (newbie->ipsa_addrfam == AF_INET6) {
1932 outbound = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6,
1933 *(uint32_t *)(newbie->ipsa_dstaddr));
3817 *dest32 = *(dest32 - (newpos >> 2));
3818 } else {
3819 dest = mp->b_rptr + ah_offset;
3820 while (--dest >= mp->b_rptr)
3821 *dest = *(dest - newpos);
3822 }
3823 freeb(phdr_mp);
3824
3825 /*
3826 * If SA is labelled, use its label, else inherit the label
3827 */
3828 if (is_system_labeled() && (assoc->ipsa_tsl != NULL)) {
3829 if (!ip_recv_attr_replace_label(ira, assoc->ipsa_tsl)) {
3830 ip_drop_packet(mp, B_TRUE, ira->ira_ill,
3831 DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper);
3832 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3833 return (NULL);
3834 }
3835 }
3836
3837 if (assoc->ipsa_state == IPSA_STATE_IDLE) {
3838 /*
3839 * Cluster buffering case. Tell caller that we're
3840 * handling the packet.
3841 */
3842 sadb_buf_pkt(assoc, mp, ira);
3843 return (NULL);
3844 }
3845
3846 return (mp);
3847
3848 ah_in_discard:
3849 IP_AH_BUMP_STAT(ipss, in_discards);
3850 ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, counter,
3851 &ahstack->ah_dropper);
3852 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3853 return (NULL);
3854 }
3855
3856 /*
3857 * Invoked after processing of an outbound packet by the
3858 * kernel crypto framework, either by ah_submit_req() for a request
3859 * executed syncrhonously, or by the KEF callback for a request
3860 * executed asynchronously.
3861 */
3862 static mblk_t *
3863 ah_auth_out_done(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, ipsec_crypto_t *ic)
3864 {
3865 mblk_t *mp;
|
1070 }
1071 if (isrcext != NULL && idstext == NULL) {
1072 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
1073 return (EINVAL);
1074 }
1075 if (assoc == NULL) {
1076 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
1077 return (EINVAL);
1078 }
1079 if (key == NULL) {
1080 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_AKEY;
1081 return (EINVAL);
1082 }
1083
1084 src = (struct sockaddr_in *)(srcext + 1);
1085 dst = (struct sockaddr_in *)(dstext + 1);
1086
1087 /* Sundry ADD-specific reality checks. */
1088 /* XXX STATS : Logging/stats here? */
1089
1090 if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) {
1091 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
1092 return (EINVAL);
1093 }
1094 if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1095 *diagnostic = SADB_X_DIAGNOSTIC_ENCR_NOTSUPP;
1096 return (EINVAL);
1097 }
1098 if (assoc->sadb_sa_flags & ~ahstack->ah_sadb.s_addflags) {
1099 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
1100 return (EINVAL);
1101 }
1102 if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0)
1103 return (EINVAL);
1104
1105 ASSERT(src->sin_family == dst->sin_family);
1106
1107 /* Stuff I don't support, for now. XXX Diagnostic? */
1108 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1109 return (EOPNOTSUPP);
1110
1148 mutex_exit(&ipss->ipsec_alg_lock);
1149 return (EINVAL);
1150 }
1151
1152 mutex_exit(&ipss->ipsec_alg_lock);
1153
1154 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1155 diagnostic, ahstack));
1156 }
1157
1158 /* Refactor me */
1159 /*
1160 * Update a security association. Updates come in two varieties. The first
1161 * is an update of lifetimes on a non-larval SA. The second is an update of
1162 * a larval SA, which ends up looking a lot more like an add.
1163 */
1164 static int
1165 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1166 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1167 {
1168 sadb_address_t *dstext =
1169 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1170
1171 if (dstext == NULL) {
1172 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
1173 return (EINVAL);
1174 }
1175
1176 return (sadb_update_sa(mp, ksi, &ahstack->ah_sadb, diagnostic,
1177 ahstack->ah_pfkey_q, ah_add_sa, ahstack->ipsecah_netstack,
1178 sadb_msg_type));
1179 }
1180
1181 /* Refactor me */
1182 /*
1183 * Delete a security association. This is REALLY likely to be code common to
1184 * both AH and ESP. Find the association, then unlink it.
1185 */
1186 static int
1187 ah_del_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1188 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1189 {
1190 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1191 sadb_address_t *dstext =
1192 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1193 sadb_address_t *srcext =
1194 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
1195 struct sockaddr_in *sin;
1196
1197 if (assoc == NULL) {
1198 if (dstext != NULL)
1305 * AF_INET.
1306 */
1307 if (!sadb_addrfix(ksi, ahstack->ah_pfkey_q, mp,
1308 ahstack->ipsecah_netstack) ||
1309 ah_pfkey_reality_failures(mp, ksi, ahstack)) {
1310 return;
1311 }
1312
1313 switch (samsg->sadb_msg_type) {
1314 case SADB_ADD:
1315 error = ah_add_sa(mp, ksi, &diagnostic,
1316 ahstack->ipsecah_netstack);
1317 if (error != 0) {
1318 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1319 diagnostic, ksi->ks_in_serial);
1320 }
1321 /* else ah_add_sa() took care of things. */
1322 break;
1323 case SADB_DELETE:
1324 case SADB_X_DELPAIR:
1325 error = ah_del_sa(mp, ksi, &diagnostic, ahstack,
1326 samsg->sadb_msg_type);
1327 if (error != 0) {
1328 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1329 diagnostic, ksi->ks_in_serial);
1330 }
1331 /* Else ah_del_sa() took care of things. */
1332 break;
1333 case SADB_GET:
1334 error = sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, &diagnostic,
1335 ahstack->ah_pfkey_q, samsg->sadb_msg_type);
1336 if (error != 0) {
1337 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1338 diagnostic, ksi->ks_in_serial);
1339 }
1340 /* Else sadb_get_sa() took care of things. */
1341 break;
1342 case SADB_FLUSH:
1343 sadbp_flush(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
1344 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, samsg, ksi, NULL);
1878
1879 /* Refactor me */
1880 /*
1881 * Handle the SADB_GETSPI message. Create a larval SA.
1882 */
1883 static void
1884 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1885 {
1886 ipsa_t *newbie, *target;
1887 isaf_t *outbound, *inbound;
1888 int rc, diagnostic;
1889 sadb_sa_t *assoc;
1890 keysock_out_t *kso;
1891 uint32_t newspi;
1892
1893 /*
1894 * Randomly generate a proposed SPI value.
1895 */
1896 (void) random_get_pseudo_bytes((uint8_t *)&newspi, sizeof (uint32_t));
1897 newbie = sadb_getspi(ksi, newspi, &diagnostic,
1898 ahstack->ipsecah_netstack);
1899
1900 if (newbie == NULL) {
1901 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, diagnostic,
1902 ksi->ks_in_serial);
1903 return;
1904 } else if (newbie == (ipsa_t *)-1) {
1905 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, diagnostic,
1906 ksi->ks_in_serial);
1907 return;
1908 }
1909
1910 /*
1911 * XXX - We may randomly collide. We really should recover from this.
1912 * Unfortunately, that could require spending way-too-much-time
1913 * in here. For now, let the user retry.
1914 */
1915
1916 if (newbie->ipsa_addrfam == AF_INET6) {
1917 outbound = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6,
1918 *(uint32_t *)(newbie->ipsa_dstaddr));
3802 *dest32 = *(dest32 - (newpos >> 2));
3803 } else {
3804 dest = mp->b_rptr + ah_offset;
3805 while (--dest >= mp->b_rptr)
3806 *dest = *(dest - newpos);
3807 }
3808 freeb(phdr_mp);
3809
3810 /*
3811 * If SA is labelled, use its label, else inherit the label
3812 */
3813 if (is_system_labeled() && (assoc->ipsa_tsl != NULL)) {
3814 if (!ip_recv_attr_replace_label(ira, assoc->ipsa_tsl)) {
3815 ip_drop_packet(mp, B_TRUE, ira->ira_ill,
3816 DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper);
3817 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3818 return (NULL);
3819 }
3820 }
3821
3822 return (mp);
3823
3824 ah_in_discard:
3825 IP_AH_BUMP_STAT(ipss, in_discards);
3826 ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, counter,
3827 &ahstack->ah_dropper);
3828 BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3829 return (NULL);
3830 }
3831
3832 /*
3833 * Invoked after processing of an outbound packet by the
3834 * kernel crypto framework, either by ah_submit_req() for a request
3835 * executed syncrhonously, or by the KEF callback for a request
3836 * executed asynchronously.
3837 */
3838 static mblk_t *
3839 ah_auth_out_done(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, ipsec_crypto_t *ic)
3840 {
3841 mblk_t *mp;
|