aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2014-06-16 10:35:28 -0400
committerSteve French <smfrench@gmail.com>2014-08-01 00:11:15 -0400
commitcc87c47d9d7ac25554aa81cd8ded56e75f79c198 (patch)
treedb8cf5f32f90a6c44cf5cfca0394a043a5b842ce /fs/cifs
parentee03c646dd70dafb28a894119f6e8f0033c974dc (diff)
cifs: Separate rawntlmssp auth from CIFS_SessSetup()
Separate rawntlmssp authentication from CIFS_SessSetup(). Also cleanup CIFS_SessSetup() since we no longer do any auth within it. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Shirish Pargaonkar <spargaonkar@suse.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/sess.c490
1 files changed, 263 insertions, 227 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index b413fae993aa..c2e7c07c9d5c 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -1113,241 +1113,225 @@ sess_auth_kerberos(struct sess_data *sess_data)
1113} 1113}
1114#endif /* ! CONFIG_CIFS_UPCALL */ 1114#endif /* ! CONFIG_CIFS_UPCALL */
1115 1115
1116int 1116/*
1117CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, 1117 * The required kvec buffers have to be allocated before calling this
1118 const struct nls_table *nls_cp) 1118 * function.
1119 */
1120static int
1121_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
1119{ 1122{
1120 int rc = 0;
1121 int wct;
1122 struct smb_hdr *smb_buf; 1123 struct smb_hdr *smb_buf;
1123 char *bcc_ptr;
1124 char *str_area;
1125 SESSION_SETUP_ANDX *pSMB; 1124 SESSION_SETUP_ANDX *pSMB;
1125 struct cifs_ses *ses = sess_data->ses;
1126 __u32 capabilities; 1126 __u32 capabilities;
1127 __u16 count; 1127 char *bcc_ptr;
1128 int resp_buf_type;
1129 struct kvec iov[3];
1130 enum securityEnum type;
1131 __u16 action, bytes_remaining;
1132 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
1133 u16 blob_len;
1134 char *ntlmsspblob = NULL;
1135 struct sess_data *sess_data;
1136 1128
1137 if (ses == NULL) { 1129 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1138 WARN(1, "%s: ses == NULL!", __func__); 1130 smb_buf = (struct smb_hdr *)pSMB;
1139 return -EINVAL; 1131
1132 capabilities = cifs_ssetup_hdr(ses, pSMB);
1133 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1134 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1135 return -ENOSYS;
1140 } 1136 }
1141 1137
1142 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL); 1138 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1143 if (!sess_data) 1139 capabilities |= CAP_EXTENDED_SECURITY;
1144 return -ENOMEM; 1140 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
1145 sess_data->xid = xid;
1146 sess_data->ses = ses;
1147 sess_data->buf0_type = CIFS_NO_BUFFER;
1148 sess_data->nls_cp = (struct nls_table *) nls_cp;
1149 1141
1150 type = select_sectype(ses->server, ses->sectype); 1142 bcc_ptr = sess_data->iov[2].iov_base;
1151 cifs_dbg(FYI, "sess setup type %d\n", type); 1143 /* unicode strings must be word aligned */
1152 if (type == Unspecified) { 1144 if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) {
1153 cifs_dbg(VFS, 1145 *bcc_ptr = 0;
1154 "Unable to select appropriate authentication method!"); 1146 bcc_ptr++;
1155 return -EINVAL;
1156 } 1147 }
1148 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1157 1149
1158 switch (type) { 1150 sess_data->iov[2].iov_len = (long) bcc_ptr -
1159 case LANMAN: 1151 (long) sess_data->iov[2].iov_base;
1160 sess_auth_lanman(sess_data);
1161 goto out;
1162 case NTLM:
1163 sess_auth_ntlm(sess_data);
1164 goto out;
1165 case NTLMv2:
1166 sess_auth_ntlmv2(sess_data);
1167 goto out;
1168 case Kerberos:
1169 sess_auth_kerberos(sess_data);
1170 goto out;
1171 default:
1172 cifs_dbg(FYI, "Continuing with CIFS_SessSetup\n");
1173 }
1174 1152
1175 if (type == RawNTLMSSP) { 1153 return 0;
1176 /* if memory allocation is successful, caller of this function 1154}
1177 * frees it. 1155
1178 */ 1156static void
1179 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL); 1157sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
1180 if (!ses->ntlmssp) 1158
1181 return -ENOMEM; 1159static void
1182 ses->ntlmssp->sesskey_per_smbsess = false; 1160sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
1161{
1162 int rc;
1163 struct smb_hdr *smb_buf;
1164 SESSION_SETUP_ANDX *pSMB;
1165 struct cifs_ses *ses = sess_data->ses;
1166 __u16 bytes_remaining;
1167 char *bcc_ptr;
1168 u16 blob_len;
1169
1170 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1183 1171
1172 /*
1173 * if memory allocation is successful, caller of this function
1174 * frees it.
1175 */
1176 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1177 if (!ses->ntlmssp) {
1178 rc = -ENOMEM;
1179 goto out;
1184 } 1180 }
1181 ses->ntlmssp->sesskey_per_smbsess = false;
1185 1182
1186ssetup_ntlmssp_authenticate: 1183 /* wct = 12 */
1187 if (phase == NtLmChallenge) 1184 rc = sess_alloc_buffer(sess_data, 12);
1188 phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ 1185 if (rc)
1186 goto out;
1189 1187
1190 /* same size: negotiate or auth, NTLMSSP or extended security */ 1188 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1191 wct = 12;
1192 1189
1193 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, 1190 /* Build security blob before we assemble the request */
1194 (void **)&smb_buf); 1191 build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses);
1192 sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
1193 sess_data->iov[1].iov_base = pSMB->req.SecurityBlob;
1194 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
1195
1196 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1195 if (rc) 1197 if (rc)
1196 return rc; 1198 goto out;
1197 1199
1198 pSMB = (SESSION_SETUP_ANDX *)smb_buf; 1200 rc = sess_sendreceive(sess_data);
1199 1201
1200 capabilities = cifs_ssetup_hdr(ses, pSMB); 1202 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1203 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1201 1204
1202 /* we will send the SMB in three pieces: 1205 /* If true, rc here is expected and not an error */
1203 a fixed length beginning part, an optional 1206 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1204 SPNEGO blob (which can be zero length), and a 1207 smb_buf->Status.CifsError ==
1205 last part which will include the strings 1208 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1206 and rest of bcc area. This allows us to avoid 1209 rc = 0;
1207 a large buffer 17K allocation */
1208 iov[0].iov_base = (char *)pSMB;
1209 iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
1210
1211 /* setting this here allows the code at the end of the function
1212 to free the request buffer if there's an error */
1213 resp_buf_type = CIFS_SMALL_BUFFER;
1214 1210
1215 /* 2000 big enough to fit max user, domain, NOS name etc. */ 1211 if (rc)
1216 str_area = kmalloc(2000, GFP_KERNEL); 1212 goto out;
1217 if (str_area == NULL) { 1213
1218 rc = -ENOMEM; 1214 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1219 goto ssetup_exit; 1215
1216 if (smb_buf->WordCount != 4) {
1217 rc = -EIO;
1218 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1219 goto out;
1220 } 1220 }
1221 bcc_ptr = str_area;
1222 1221
1223 iov[1].iov_base = NULL; 1222 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1224 iov[1].iov_len = 0; 1223 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1225 1224
1226 if (type == RawNTLMSSP) { 1225 bytes_remaining = get_bcc(smb_buf);
1227 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { 1226 bcc_ptr = pByteArea(smb_buf);
1228 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1229 rc = -ENOSYS;
1230 goto ssetup_exit;
1231 }
1232 1227
1233 cifs_dbg(FYI, "ntlmssp session setup phase %d\n", phase); 1228 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1234 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 1229 if (blob_len > bytes_remaining) {
1235 capabilities |= CAP_EXTENDED_SECURITY; 1230 cifs_dbg(VFS, "bad security blob length %d\n",
1236 pSMB->req.Capabilities |= cpu_to_le32(capabilities); 1231 blob_len);
1237 switch(phase) { 1232 rc = -EINVAL;
1238 case NtLmNegotiate: 1233 goto out;
1239 build_ntlmssp_negotiate_blob( 1234 }
1240 pSMB->req.SecurityBlob, ses);
1241 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
1242 iov[1].iov_base = pSMB->req.SecurityBlob;
1243 pSMB->req.SecurityBlobLength =
1244 cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
1245 break;
1246 case NtLmAuthenticate:
1247 /*
1248 * 5 is an empirical value, large enough to hold
1249 * authenticate message plus max 10 of av paris,
1250 * domain, user, workstation names, flags, etc.
1251 */
1252 ntlmsspblob = kzalloc(
1253 5*sizeof(struct _AUTHENTICATE_MESSAGE),
1254 GFP_KERNEL);
1255 if (!ntlmsspblob) {
1256 rc = -ENOMEM;
1257 goto ssetup_exit;
1258 }
1259 1235
1260 rc = build_ntlmssp_auth_blob(ntlmsspblob, 1236 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
1261 &blob_len, ses, nls_cp); 1237out:
1262 if (rc) 1238 sess_free_buffer(sess_data);
1263 goto ssetup_exit; 1239
1264 iov[1].iov_len = blob_len; 1240 if (!rc) {
1265 iov[1].iov_base = ntlmsspblob; 1241 sess_data->func = sess_auth_rawntlmssp_authenticate;
1266 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len); 1242 return;
1267 /*
1268 * Make sure that we tell the server that we are using
1269 * the uid that it just gave us back on the response
1270 * (challenge)
1271 */
1272 smb_buf->Uid = ses->Suid;
1273 break;
1274 default:
1275 cifs_dbg(VFS, "invalid phase %d\n", phase);
1276 rc = -ENOSYS;
1277 goto ssetup_exit;
1278 }
1279 /* unicode strings must be word aligned */
1280 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
1281 *bcc_ptr = 0;
1282 bcc_ptr++;
1283 }
1284 unicode_oslm_strings(&bcc_ptr, nls_cp);
1285 } else {
1286 cifs_dbg(VFS, "secType %d not supported!\n", type);
1287 rc = -ENOSYS;
1288 goto ssetup_exit;
1289 } 1243 }
1290 1244
1291 iov[2].iov_base = str_area; 1245 /* Else error. Cleanup */
1292 iov[2].iov_len = (long) bcc_ptr - (long) str_area; 1246 kfree(ses->auth_key.response);
1247 ses->auth_key.response = NULL;
1248 kfree(ses->ntlmssp);
1249 ses->ntlmssp = NULL;
1293 1250
1294 count = iov[1].iov_len + iov[2].iov_len; 1251 sess_data->func = NULL;
1295 smb_buf->smb_buf_length = 1252 sess_data->result = rc;
1296 cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count); 1253}
1297 1254
1298 put_bcc(count, smb_buf); 1255static void
1256sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1257{
1258 int rc;
1259 struct smb_hdr *smb_buf;
1260 SESSION_SETUP_ANDX *pSMB;
1261 struct cifs_ses *ses = sess_data->ses;
1262 __u16 bytes_remaining;
1263 char *bcc_ptr;
1264 char *ntlmsspblob = NULL;
1265 u16 blob_len;
1299 1266
1300 rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, 1267 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1301 CIFS_LOG_ERROR);
1302 /* SMB request buf freed in SendReceive2 */
1303 1268
1304 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; 1269 /* wct = 12 */
1305 smb_buf = (struct smb_hdr *)iov[0].iov_base; 1270 rc = sess_alloc_buffer(sess_data, 12);
1271 if (rc)
1272 goto out;
1306 1273
1307 if ((type == RawNTLMSSP) && (resp_buf_type != CIFS_NO_BUFFER) && 1274 /* Build security blob before we assemble the request */
1308 (smb_buf->Status.CifsError == 1275 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1309 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) { 1276 smb_buf = (struct smb_hdr *)pSMB;
1310 if (phase != NtLmNegotiate) { 1277 /*
1311 cifs_dbg(VFS, "Unexpected more processing error\n"); 1278 * 5 is an empirical value, large enough to hold
1312 goto ssetup_exit; 1279 * authenticate message plus max 10 of av paris,
1313 } 1280 * domain, user, workstation names, flags, etc.
1314 /* NTLMSSP Negotiate sent now processing challenge (response) */ 1281 */
1315 phase = NtLmChallenge; /* process ntlmssp challenge */ 1282 ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE),
1316 rc = 0; /* MORE_PROC rc is not an error here, but expected */ 1283 GFP_KERNEL);
1284 if (!ntlmsspblob) {
1285 rc = -ENOMEM;
1286 goto out;
1317 } 1287 }
1288
1289 rc = build_ntlmssp_auth_blob(ntlmsspblob,
1290 &blob_len, ses, sess_data->nls_cp);
1291 if (rc)
1292 goto out_free_ntlmsspblob;
1293 sess_data->iov[1].iov_len = blob_len;
1294 sess_data->iov[1].iov_base = ntlmsspblob;
1295 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1296 /*
1297 * Make sure that we tell the server that we are using
1298 * the uid that it just gave us back on the response
1299 * (challenge)
1300 */
1301 smb_buf->Uid = ses->Suid;
1302
1303 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1318 if (rc) 1304 if (rc)
1319 goto ssetup_exit; 1305 goto out_free_ntlmsspblob;
1320 1306
1307 rc = sess_sendreceive(sess_data);
1308 if (rc)
1309 goto out_free_ntlmsspblob;
1310
1311 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1312 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1321 if (smb_buf->WordCount != 4) { 1313 if (smb_buf->WordCount != 4) {
1322 rc = -EIO; 1314 rc = -EIO;
1323 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); 1315 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1324 goto ssetup_exit; 1316 goto out_free_ntlmsspblob;
1325 } 1317 }
1326 action = le16_to_cpu(pSMB->resp.Action); 1318
1327 if (action & GUEST_LOGIN) 1319 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1328 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */ 1320 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1329 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ 1321
1330 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1331 /* response can have either 3 or 4 word count - Samba sends 3 */
1332 /* and lanman response is 3 */
1333 bytes_remaining = get_bcc(smb_buf); 1322 bytes_remaining = get_bcc(smb_buf);
1334 bcc_ptr = pByteArea(smb_buf); 1323 bcc_ptr = pByteArea(smb_buf);
1335
1336 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); 1324 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1337 if (blob_len > bytes_remaining) { 1325 if (blob_len > bytes_remaining) {
1338 cifs_dbg(VFS, "bad security blob length %d\n", 1326 cifs_dbg(VFS, "bad security blob length %d\n",
1339 blob_len); 1327 blob_len);
1340 rc = -EINVAL; 1328 rc = -EINVAL;
1341 goto ssetup_exit; 1329 goto out_free_ntlmsspblob;
1342 }
1343 if (phase == NtLmChallenge) {
1344 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
1345 if (rc)
1346 goto ssetup_exit;
1347 } 1330 }
1348 bcc_ptr += blob_len; 1331 bcc_ptr += blob_len;
1349 bytes_remaining -= blob_len; 1332 bytes_remaining -= blob_len;
1350 1333
1334
1351 /* BB check if Unicode and decode strings */ 1335 /* BB check if Unicode and decode strings */
1352 if (bytes_remaining == 0) { 1336 if (bytes_remaining == 0) {
1353 /* no string area to decode, do nothing */ 1337 /* no string area to decode, do nothing */
@@ -1357,61 +1341,113 @@ ssetup_ntlmssp_authenticate:
1357 ++bcc_ptr; 1341 ++bcc_ptr;
1358 --bytes_remaining; 1342 --bytes_remaining;
1359 } 1343 }
1360 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); 1344 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1345 sess_data->nls_cp);
1361 } else { 1346 } else {
1362 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); 1347 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1348 sess_data->nls_cp);
1363 } 1349 }
1364 1350
1365ssetup_exit: 1351out_free_ntlmsspblob:
1366 kfree(str_area);
1367 kfree(ntlmsspblob); 1352 kfree(ntlmsspblob);
1368 ntlmsspblob = NULL; 1353out:
1369 if (resp_buf_type == CIFS_SMALL_BUFFER) { 1354 sess_free_buffer(sess_data);
1370 cifs_dbg(FYI, "ssetup freeing small buf %p\n", iov[0].iov_base);
1371 cifs_small_buf_release(iov[0].iov_base);
1372 } else if (resp_buf_type == CIFS_LARGE_BUFFER)
1373 cifs_buf_release(iov[0].iov_base);
1374
1375 /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
1376 if ((phase == NtLmChallenge) && (rc == 0))
1377 goto ssetup_ntlmssp_authenticate;
1378
1379 if (!rc) {
1380 mutex_lock(&ses->server->srv_mutex);
1381 if (!ses->server->session_estab) {
1382 if (ses->server->sign) {
1383 ses->server->session_key.response =
1384 kmemdup(ses->auth_key.response,
1385 ses->auth_key.len, GFP_KERNEL);
1386 if (!ses->server->session_key.response) {
1387 rc = -ENOMEM;
1388 mutex_unlock(&ses->server->srv_mutex);
1389 goto keycp_exit;
1390 }
1391 ses->server->session_key.len =
1392 ses->auth_key.len;
1393 }
1394 ses->server->sequence_number = 0x2;
1395 ses->server->session_estab = true;
1396 }
1397 mutex_unlock(&ses->server->srv_mutex);
1398 1355
1399 cifs_dbg(FYI, "CIFS session established successfully\n"); 1356 if (!rc)
1400 spin_lock(&GlobalMid_Lock); 1357 rc = sess_establish_session(sess_data);
1401 ses->status = CifsGood;
1402 ses->need_reconnect = false;
1403 spin_unlock(&GlobalMid_Lock);
1404 }
1405 1358
1406keycp_exit: 1359 /* Cleanup */
1407 kfree(ses->auth_key.response); 1360 kfree(ses->auth_key.response);
1408 ses->auth_key.response = NULL; 1361 ses->auth_key.response = NULL;
1409 kfree(ses->ntlmssp); 1362 kfree(ses->ntlmssp);
1363 ses->ntlmssp = NULL;
1410 1364
1411 return rc; 1365 sess_data->func = NULL;
1366 sess_data->result = rc;
1367}
1412 1368
1413out: 1369int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
1370{
1371 int type;
1372
1373 type = select_sectype(ses->server, ses->sectype);
1374 cifs_dbg(FYI, "sess setup type %d\n", type);
1375 if (type == Unspecified) {
1376 cifs_dbg(VFS,
1377 "Unable to select appropriate authentication method!");
1378 return -EINVAL;
1379 }
1380
1381 switch (type) {
1382 case LANMAN:
1383 /* LANMAN and plaintext are less secure and off by default.
1384 * So we make this explicitly be turned on in kconfig (in the
1385 * build) and turned on at runtime (changed from the default)
1386 * in proc/fs/cifs or via mount parm. Unfortunately this is
1387 * needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
1388#ifdef CONFIG_CIFS_WEAK_PW_HASH
1389 sess_data->func = sess_auth_lanman;
1390 break;
1391#else
1392 return -EOPNOTSUPP;
1393#endif
1394 case NTLM:
1395 sess_data->func = sess_auth_ntlm;
1396 break;
1397 case NTLMv2:
1398 sess_data->func = sess_auth_ntlmv2;
1399 break;
1400 case Kerberos:
1401#ifdef CONFIG_CIFS_UPCALL
1402 sess_data->func = sess_auth_kerberos;
1403 break;
1404#else
1405 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1406 return -ENOSYS;
1407 break;
1408#endif /* CONFIG_CIFS_UPCALL */
1409 case RawNTLMSSP:
1410 sess_data->func = sess_auth_rawntlmssp_negotiate;
1411 break;
1412 default:
1413 cifs_dbg(VFS, "secType %d not supported!\n", type);
1414 return -ENOSYS;
1415 }
1416
1417 return 0;
1418}
1419
1420int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
1421 const struct nls_table *nls_cp)
1422{
1423 int rc = 0;
1424 struct sess_data *sess_data;
1425
1426 if (ses == NULL) {
1427 WARN(1, "%s: ses == NULL!", __func__);
1428 return -EINVAL;
1429 }
1430
1431 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1432 if (!sess_data)
1433 return -ENOMEM;
1434
1435 rc = select_sec(ses, sess_data);
1436 if (rc)
1437 goto out;
1438
1439 sess_data->xid = xid;
1440 sess_data->ses = ses;
1441 sess_data->buf0_type = CIFS_NO_BUFFER;
1442 sess_data->nls_cp = (struct nls_table *) nls_cp;
1443
1444 while (sess_data->func)
1445 sess_data->func(sess_data);
1446
1447 /* Store result before we free sess_data */
1414 rc = sess_data->result; 1448 rc = sess_data->result;
1449
1450out:
1415 kfree(sess_data); 1451 kfree(sess_data);
1416 return rc; 1452 return rc;
1417} 1453}