1 // SPDX-License-Identifier: LGPL-2.1
4 * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
5 * for more detailed information
7 * Copyright (C) International Business Machines Corp., 2005,2013
8 * Author(s): Steve French (sfrench@us.ibm.com)
13 #include <linux/slab.h>
16 #include "cifs_debug.h"
17 #include "cifs_unicode.h"
18 #include "cifsproto.h"
20 #include <linux/ctype.h>
21 #include <linux/random.h>
22 #include <linux/highmem.h>
23 #include <linux/fips.h>
24 #include <linux/iov_iter.h>
25 #include "../common/arc4.h"
26 #include <crypto/aead.h>
28 static size_t cifs_shash_step(void *iter_base
, size_t progress
, size_t len
,
29 void *priv
, void *priv2
)
31 struct shash_desc
*shash
= priv
;
32 int ret
, *pret
= priv2
;
34 ret
= crypto_shash_update(shash
, iter_base
, len
);
43 * Pass the data from an iterator into a hash.
45 static int cifs_shash_iter(const struct iov_iter
*iter
, size_t maxsize
,
46 struct shash_desc
*shash
)
48 struct iov_iter tmp_iter
= *iter
;
51 if (iterate_and_advance_kernel(&tmp_iter
, maxsize
, shash
, &err
,
52 cifs_shash_step
) != maxsize
)
57 int __cifs_calc_signature(struct smb_rqst
*rqst
,
58 struct TCP_Server_Info
*server
, char *signature
,
59 struct shash_desc
*shash
)
63 struct kvec
*iov
= rqst
->rq_iov
;
64 int n_vec
= rqst
->rq_nvec
;
66 /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
67 if (!is_smb1(server
)) {
68 if (iov
[0].iov_len
<= 4)
72 if (n_vec
< 2 || iov
[0].iov_len
!= 4)
74 i
= 1; /* skip rfc1002 length */
77 for (; i
< n_vec
; i
++) {
78 if (iov
[i
].iov_len
== 0)
80 if (iov
[i
].iov_base
== NULL
) {
81 cifs_dbg(VFS
, "null iovec entry\n");
85 rc
= crypto_shash_update(shash
,
86 iov
[i
].iov_base
, iov
[i
].iov_len
);
88 cifs_dbg(VFS
, "%s: Could not update with payload\n",
94 rc
= cifs_shash_iter(&rqst
->rq_iter
, iov_iter_count(&rqst
->rq_iter
), shash
);
98 rc
= crypto_shash_final(shash
, signature
);
100 cifs_dbg(VFS
, "%s: Could not generate hash\n", __func__
);
106 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
107 * The 16 byte signature must be allocated by the caller. Note we only use the
108 * 1st eight bytes and that the smb header signature field on input contains
109 * the sequence number before this function is called. Also, this function
110 * should be called with the server->srv_mutex held.
112 static int cifs_calc_signature(struct smb_rqst
*rqst
,
113 struct TCP_Server_Info
*server
, char *signature
)
117 if (!rqst
->rq_iov
|| !signature
|| !server
)
120 rc
= cifs_alloc_hash("md5", &server
->secmech
.md5
);
124 rc
= crypto_shash_init(server
->secmech
.md5
);
126 cifs_dbg(VFS
, "%s: Could not init md5\n", __func__
);
130 rc
= crypto_shash_update(server
->secmech
.md5
,
131 server
->session_key
.response
, server
->session_key
.len
);
133 cifs_dbg(VFS
, "%s: Could not update with response\n", __func__
);
137 return __cifs_calc_signature(rqst
, server
, signature
, server
->secmech
.md5
);
140 /* must be called with server->srv_mutex held */
141 int cifs_sign_rqst(struct smb_rqst
*rqst
, struct TCP_Server_Info
*server
,
142 __u32
*pexpected_response_sequence_number
)
145 char smb_signature
[20];
146 struct smb_hdr
*cifs_pdu
= (struct smb_hdr
*)rqst
->rq_iov
[0].iov_base
;
148 if (rqst
->rq_iov
[0].iov_len
!= 4 ||
149 rqst
->rq_iov
[0].iov_base
+ 4 != rqst
->rq_iov
[1].iov_base
)
152 if ((cifs_pdu
== NULL
) || (server
== NULL
))
155 spin_lock(&server
->srv_lock
);
156 if (!(cifs_pdu
->Flags2
& SMBFLG2_SECURITY_SIGNATURE
) ||
157 server
->tcpStatus
== CifsNeedNegotiate
) {
158 spin_unlock(&server
->srv_lock
);
161 spin_unlock(&server
->srv_lock
);
163 if (!server
->session_estab
) {
164 memcpy(cifs_pdu
->Signature
.SecuritySignature
, "BSRSPYL", 8);
168 cifs_pdu
->Signature
.Sequence
.SequenceNumber
=
169 cpu_to_le32(server
->sequence_number
);
170 cifs_pdu
->Signature
.Sequence
.Reserved
= 0;
172 *pexpected_response_sequence_number
= ++server
->sequence_number
;
173 ++server
->sequence_number
;
175 rc
= cifs_calc_signature(rqst
, server
, smb_signature
);
177 memset(cifs_pdu
->Signature
.SecuritySignature
, 0, 8);
179 memcpy(cifs_pdu
->Signature
.SecuritySignature
, smb_signature
, 8);
184 int cifs_sign_smbv(struct kvec
*iov
, int n_vec
, struct TCP_Server_Info
*server
,
185 __u32
*pexpected_response_sequence
)
187 struct smb_rqst rqst
= { .rq_iov
= iov
,
190 return cifs_sign_rqst(&rqst
, server
, pexpected_response_sequence
);
193 /* must be called with server->srv_mutex held */
194 int cifs_sign_smb(struct smb_hdr
*cifs_pdu
, struct TCP_Server_Info
*server
,
195 __u32
*pexpected_response_sequence_number
)
199 iov
[0].iov_base
= cifs_pdu
;
201 iov
[1].iov_base
= (char *)cifs_pdu
+ 4;
202 iov
[1].iov_len
= be32_to_cpu(cifs_pdu
->smb_buf_length
);
204 return cifs_sign_smbv(iov
, 2, server
,
205 pexpected_response_sequence_number
);
208 int cifs_verify_signature(struct smb_rqst
*rqst
,
209 struct TCP_Server_Info
*server
,
210 __u32 expected_sequence_number
)
213 char server_response_sig
[8];
214 char what_we_think_sig_should_be
[20];
215 struct smb_hdr
*cifs_pdu
= (struct smb_hdr
*)rqst
->rq_iov
[0].iov_base
;
217 if (rqst
->rq_iov
[0].iov_len
!= 4 ||
218 rqst
->rq_iov
[0].iov_base
+ 4 != rqst
->rq_iov
[1].iov_base
)
221 if (cifs_pdu
== NULL
|| server
== NULL
)
224 if (!server
->session_estab
)
227 if (cifs_pdu
->Command
== SMB_COM_LOCKING_ANDX
) {
228 struct smb_com_lock_req
*pSMB
=
229 (struct smb_com_lock_req
*)cifs_pdu
;
230 if (pSMB
->LockType
& LOCKING_ANDX_OPLOCK_RELEASE
)
234 /* BB what if signatures are supposed to be on for session but
235 server does not send one? BB */
237 /* Do not need to verify session setups with signature "BSRSPYL " */
238 if (memcmp(cifs_pdu
->Signature
.SecuritySignature
, "BSRSPYL ", 8) == 0)
239 cifs_dbg(FYI
, "dummy signature received for smb command 0x%x\n",
242 /* save off the original signature so we can modify the smb and check
243 its signature against what the server sent */
244 memcpy(server_response_sig
, cifs_pdu
->Signature
.SecuritySignature
, 8);
246 cifs_pdu
->Signature
.Sequence
.SequenceNumber
=
247 cpu_to_le32(expected_sequence_number
);
248 cifs_pdu
->Signature
.Sequence
.Reserved
= 0;
250 cifs_server_lock(server
);
251 rc
= cifs_calc_signature(rqst
, server
, what_we_think_sig_should_be
);
252 cifs_server_unlock(server
);
257 /* cifs_dump_mem("what we think it should be: ",
258 what_we_think_sig_should_be, 16); */
260 if (memcmp(server_response_sig
, what_we_think_sig_should_be
, 8))
267 /* Build a proper attribute value/target info pairs blob.
268 * Fill in netbios and dns domain name and workstation name
269 * and client time (total five av pairs and + one end of fields indicator.
270 * Allocate domain name which gets freed when session struct is deallocated.
273 build_avpair_blob(struct cifs_ses
*ses
, const struct nls_table
*nls_cp
)
276 unsigned int size
= 2 * sizeof(struct ntlmssp2_name
);
277 char *defdmname
= "WORKGROUP";
278 unsigned char *blobptr
;
279 struct ntlmssp2_name
*attrptr
;
281 if (!ses
->domainName
) {
282 ses
->domainName
= kstrdup(defdmname
, GFP_KERNEL
);
283 if (!ses
->domainName
)
287 dlen
= strlen(ses
->domainName
);
290 * The length of this blob is two times the size of a
291 * structure (av pair) which holds name/size
292 * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
293 * unicode length of a netbios domain name
295 kfree_sensitive(ses
->auth_key
.response
);
296 ses
->auth_key
.len
= size
+ 2 * dlen
;
297 ses
->auth_key
.response
= kzalloc(ses
->auth_key
.len
, GFP_KERNEL
);
298 if (!ses
->auth_key
.response
) {
299 ses
->auth_key
.len
= 0;
303 blobptr
= ses
->auth_key
.response
;
304 attrptr
= (struct ntlmssp2_name
*) blobptr
;
307 * As defined in MS-NTLM 3.3.2, just this av pair field
308 * is sufficient as part of the temp
310 attrptr
->type
= cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME
);
311 attrptr
->length
= cpu_to_le16(2 * dlen
);
312 blobptr
= (unsigned char *)attrptr
+ sizeof(struct ntlmssp2_name
);
313 cifs_strtoUTF16((__le16
*)blobptr
, ses
->domainName
, dlen
, nls_cp
);
318 /* Server has provided av pairs/target info in the type 2 challenge
319 * packet and we have plucked it and stored within smb session.
320 * We parse that blob here to find netbios domain name to be used
321 * as part of ntlmv2 authentication (in Target String), if not already
322 * specified on the command line.
323 * If this function returns without any error but without fetching
324 * domain name, authentication may fail against some server but
325 * may not fail against other (those who are not very particular
326 * about target string i.e. for some, just user name might suffice.
329 find_domain_name(struct cifs_ses
*ses
, const struct nls_table
*nls_cp
)
331 unsigned int attrsize
;
333 unsigned int onesize
= sizeof(struct ntlmssp2_name
);
334 unsigned char *blobptr
;
335 unsigned char *blobend
;
336 struct ntlmssp2_name
*attrptr
;
338 if (!ses
->auth_key
.len
|| !ses
->auth_key
.response
)
341 blobptr
= ses
->auth_key
.response
;
342 blobend
= blobptr
+ ses
->auth_key
.len
;
344 while (blobptr
+ onesize
< blobend
) {
345 attrptr
= (struct ntlmssp2_name
*) blobptr
;
346 type
= le16_to_cpu(attrptr
->type
);
347 if (type
== NTLMSSP_AV_EOL
)
349 blobptr
+= 2; /* advance attr type */
350 attrsize
= le16_to_cpu(attrptr
->length
);
351 blobptr
+= 2; /* advance attr size */
352 if (blobptr
+ attrsize
> blobend
)
354 if (type
== NTLMSSP_AV_NB_DOMAIN_NAME
) {
355 if (!attrsize
|| attrsize
>= CIFS_MAX_DOMAINNAME_LEN
)
357 if (!ses
->domainName
) {
359 kmalloc(attrsize
+ 1, GFP_KERNEL
);
360 if (!ses
->domainName
)
362 cifs_from_utf16(ses
->domainName
,
363 (__le16
*)blobptr
, attrsize
, attrsize
,
364 nls_cp
, NO_MAP_UNI_RSVD
);
368 blobptr
+= attrsize
; /* advance attr value */
374 /* Server has provided av pairs/target info in the type 2 challenge
375 * packet and we have plucked it and stored within smb session.
376 * We parse that blob here to find the server given timestamp
377 * as part of ntlmv2 authentication (or local current time as
378 * default in case of failure)
381 find_timestamp(struct cifs_ses
*ses
)
383 unsigned int attrsize
;
385 unsigned int onesize
= sizeof(struct ntlmssp2_name
);
386 unsigned char *blobptr
;
387 unsigned char *blobend
;
388 struct ntlmssp2_name
*attrptr
;
389 struct timespec64 ts
;
391 if (!ses
->auth_key
.len
|| !ses
->auth_key
.response
)
394 blobptr
= ses
->auth_key
.response
;
395 blobend
= blobptr
+ ses
->auth_key
.len
;
397 while (blobptr
+ onesize
< blobend
) {
398 attrptr
= (struct ntlmssp2_name
*) blobptr
;
399 type
= le16_to_cpu(attrptr
->type
);
400 if (type
== NTLMSSP_AV_EOL
)
402 blobptr
+= 2; /* advance attr type */
403 attrsize
= le16_to_cpu(attrptr
->length
);
404 blobptr
+= 2; /* advance attr size */
405 if (blobptr
+ attrsize
> blobend
)
407 if (type
== NTLMSSP_AV_TIMESTAMP
) {
408 if (attrsize
== sizeof(u64
))
409 return *((__le64
*)blobptr
);
411 blobptr
+= attrsize
; /* advance attr value */
414 ktime_get_real_ts64(&ts
);
415 return cpu_to_le64(cifs_UnixTimeToNT(ts
));
418 static int calc_ntlmv2_hash(struct cifs_ses
*ses
, char *ntlmv2_hash
,
419 const struct nls_table
*nls_cp
, struct shash_desc
*hmacmd5
)
423 char nt_hash
[CIFS_NTHASH_SIZE
];
428 /* calculate md4 hash of password */
429 E_md4hash(ses
->password
, nt_hash
, nls_cp
);
431 rc
= crypto_shash_setkey(hmacmd5
->tfm
, nt_hash
, CIFS_NTHASH_SIZE
);
433 cifs_dbg(VFS
, "%s: Could not set NT hash as a key, rc=%d\n", __func__
, rc
);
437 rc
= crypto_shash_init(hmacmd5
);
439 cifs_dbg(VFS
, "%s: Could not init HMAC-MD5, rc=%d\n", __func__
, rc
);
443 /* convert ses->user_name to unicode */
444 len
= ses
->user_name
? strlen(ses
->user_name
) : 0;
445 user
= kmalloc(2 + (len
* 2), GFP_KERNEL
);
450 len
= cifs_strtoUTF16(user
, ses
->user_name
, len
, nls_cp
);
456 rc
= crypto_shash_update(hmacmd5
, (char *)user
, 2 * len
);
459 cifs_dbg(VFS
, "%s: Could not update with user, rc=%d\n", __func__
, rc
);
463 /* convert ses->domainName to unicode and uppercase */
464 if (ses
->domainName
) {
465 len
= strlen(ses
->domainName
);
467 domain
= kmalloc(2 + (len
* 2), GFP_KERNEL
);
471 len
= cifs_strtoUTF16((__le16
*)domain
, ses
->domainName
, len
,
473 rc
= crypto_shash_update(hmacmd5
, (char *)domain
, 2 * len
);
476 cifs_dbg(VFS
, "%s: Could not update with domain, rc=%d\n", __func__
, rc
);
480 /* We use ses->ip_addr if no domain name available */
481 len
= strlen(ses
->ip_addr
);
483 server
= kmalloc(2 + (len
* 2), GFP_KERNEL
);
487 len
= cifs_strtoUTF16((__le16
*)server
, ses
->ip_addr
, len
, nls_cp
);
488 rc
= crypto_shash_update(hmacmd5
, (char *)server
, 2 * len
);
491 cifs_dbg(VFS
, "%s: Could not update with server, rc=%d\n", __func__
, rc
);
496 rc
= crypto_shash_final(hmacmd5
, ntlmv2_hash
);
498 cifs_dbg(VFS
, "%s: Could not generate MD5 hash, rc=%d\n", __func__
, rc
);
504 CalcNTLMv2_response(const struct cifs_ses
*ses
, char *ntlmv2_hash
, struct shash_desc
*hmacmd5
)
507 struct ntlmv2_resp
*ntlmv2
= (struct ntlmv2_resp
*)
508 (ses
->auth_key
.response
+ CIFS_SESS_KEY_SIZE
);
509 unsigned int hash_len
;
511 /* The MD5 hash starts at challenge_key.key */
512 hash_len
= ses
->auth_key
.len
- (CIFS_SESS_KEY_SIZE
+
513 offsetof(struct ntlmv2_resp
, challenge
.key
[0]));
515 rc
= crypto_shash_setkey(hmacmd5
->tfm
, ntlmv2_hash
, CIFS_HMAC_MD5_HASH_SIZE
);
517 cifs_dbg(VFS
, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__
, rc
);
521 rc
= crypto_shash_init(hmacmd5
);
523 cifs_dbg(VFS
, "%s: Could not init HMAC-MD5, rc=%d\n", __func__
, rc
);
527 if (ses
->server
->negflavor
== CIFS_NEGFLAVOR_EXTENDED
)
528 memcpy(ntlmv2
->challenge
.key
, ses
->ntlmssp
->cryptkey
, CIFS_SERVER_CHALLENGE_SIZE
);
530 memcpy(ntlmv2
->challenge
.key
, ses
->server
->cryptkey
, CIFS_SERVER_CHALLENGE_SIZE
);
532 rc
= crypto_shash_update(hmacmd5
, ntlmv2
->challenge
.key
, hash_len
);
534 cifs_dbg(VFS
, "%s: Could not update with response, rc=%d\n", __func__
, rc
);
538 /* Note that the MD5 digest over writes anon.challenge_key.key */
539 rc
= crypto_shash_final(hmacmd5
, ntlmv2
->ntlmv2_hash
);
541 cifs_dbg(VFS
, "%s: Could not generate MD5 hash, rc=%d\n", __func__
, rc
);
547 setup_ntlmv2_rsp(struct cifs_ses
*ses
, const struct nls_table
*nls_cp
)
549 struct shash_desc
*hmacmd5
= NULL
;
553 struct ntlmv2_resp
*ntlmv2
;
554 char ntlmv2_hash
[16];
555 unsigned char *tiblob
= NULL
; /* target info blob */
556 __le64 rsp_timestamp
;
558 if (nls_cp
== NULL
) {
559 cifs_dbg(VFS
, "%s called with nls_cp==NULL\n", __func__
);
563 if (ses
->server
->negflavor
== CIFS_NEGFLAVOR_EXTENDED
) {
564 if (!ses
->domainName
) {
565 if (ses
->domainAuto
) {
566 rc
= find_domain_name(ses
, nls_cp
);
568 cifs_dbg(VFS
, "error %d finding domain name\n",
570 goto setup_ntlmv2_rsp_ret
;
573 ses
->domainName
= kstrdup("", GFP_KERNEL
);
577 rc
= build_avpair_blob(ses
, nls_cp
);
579 cifs_dbg(VFS
, "error %d building av pair blob\n", rc
);
580 goto setup_ntlmv2_rsp_ret
;
584 /* Must be within 5 minutes of the server (or in range +/-2h
585 * in case of Mac OS X), so simply carry over server timestamp
586 * (as Windows 7 does)
588 rsp_timestamp
= find_timestamp(ses
);
590 baselen
= CIFS_SESS_KEY_SIZE
+ sizeof(struct ntlmv2_resp
);
591 tilen
= ses
->auth_key
.len
;
592 tiblob
= ses
->auth_key
.response
;
594 ses
->auth_key
.response
= kmalloc(baselen
+ tilen
, GFP_KERNEL
);
595 if (!ses
->auth_key
.response
) {
597 ses
->auth_key
.len
= 0;
598 goto setup_ntlmv2_rsp_ret
;
600 ses
->auth_key
.len
+= baselen
;
602 ntlmv2
= (struct ntlmv2_resp
*)
603 (ses
->auth_key
.response
+ CIFS_SESS_KEY_SIZE
);
604 ntlmv2
->blob_signature
= cpu_to_le32(0x00000101);
605 ntlmv2
->reserved
= 0;
606 ntlmv2
->time
= rsp_timestamp
;
608 get_random_bytes(&ntlmv2
->client_chal
, sizeof(ntlmv2
->client_chal
));
609 ntlmv2
->reserved2
= 0;
611 memcpy(ses
->auth_key
.response
+ baselen
, tiblob
, tilen
);
613 cifs_server_lock(ses
->server
);
615 rc
= cifs_alloc_hash("hmac(md5)", &hmacmd5
);
617 cifs_dbg(VFS
, "Could not allocate HMAC-MD5, rc=%d\n", rc
);
621 /* calculate ntlmv2_hash */
622 rc
= calc_ntlmv2_hash(ses
, ntlmv2_hash
, nls_cp
, hmacmd5
);
624 cifs_dbg(VFS
, "Could not get NTLMv2 hash, rc=%d\n", rc
);
628 /* calculate first part of the client response (CR1) */
629 rc
= CalcNTLMv2_response(ses
, ntlmv2_hash
, hmacmd5
);
631 cifs_dbg(VFS
, "Could not calculate CR1, rc=%d\n", rc
);
635 /* now calculate the session key for NTLMv2 */
636 rc
= crypto_shash_setkey(hmacmd5
->tfm
, ntlmv2_hash
, CIFS_HMAC_MD5_HASH_SIZE
);
638 cifs_dbg(VFS
, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__
, rc
);
642 rc
= crypto_shash_init(hmacmd5
);
644 cifs_dbg(VFS
, "%s: Could not init HMAC-MD5, rc=%d\n", __func__
, rc
);
648 rc
= crypto_shash_update(hmacmd5
, ntlmv2
->ntlmv2_hash
, CIFS_HMAC_MD5_HASH_SIZE
);
650 cifs_dbg(VFS
, "%s: Could not update with response, rc=%d\n", __func__
, rc
);
654 rc
= crypto_shash_final(hmacmd5
, ses
->auth_key
.response
);
656 cifs_dbg(VFS
, "%s: Could not generate MD5 hash, rc=%d\n", __func__
, rc
);
658 cifs_server_unlock(ses
->server
);
659 cifs_free_hash(&hmacmd5
);
660 setup_ntlmv2_rsp_ret
:
661 kfree_sensitive(tiblob
);
667 calc_seckey(struct cifs_ses
*ses
)
669 unsigned char sec_key
[CIFS_SESS_KEY_SIZE
]; /* a nonce */
670 struct arc4_ctx
*ctx_arc4
;
675 get_random_bytes(sec_key
, CIFS_SESS_KEY_SIZE
);
677 ctx_arc4
= kmalloc(sizeof(*ctx_arc4
), GFP_KERNEL
);
679 cifs_dbg(VFS
, "Could not allocate arc4 context\n");
683 cifs_arc4_setkey(ctx_arc4
, ses
->auth_key
.response
, CIFS_SESS_KEY_SIZE
);
684 cifs_arc4_crypt(ctx_arc4
, ses
->ntlmssp
->ciphertext
, sec_key
,
687 /* make secondary_key/nonce as session key */
688 memcpy(ses
->auth_key
.response
, sec_key
, CIFS_SESS_KEY_SIZE
);
689 /* and make len as that of session key only */
690 ses
->auth_key
.len
= CIFS_SESS_KEY_SIZE
;
692 memzero_explicit(sec_key
, CIFS_SESS_KEY_SIZE
);
693 kfree_sensitive(ctx_arc4
);
698 cifs_crypto_secmech_release(struct TCP_Server_Info
*server
)
700 cifs_free_hash(&server
->secmech
.aes_cmac
);
701 cifs_free_hash(&server
->secmech
.hmacsha256
);
702 cifs_free_hash(&server
->secmech
.md5
);
703 cifs_free_hash(&server
->secmech
.sha512
);
705 if (!SERVER_IS_CHAN(server
)) {
706 if (server
->secmech
.enc
) {
707 crypto_free_aead(server
->secmech
.enc
);
708 server
->secmech
.enc
= NULL
;
711 if (server
->secmech
.dec
) {
712 crypto_free_aead(server
->secmech
.dec
);
713 server
->secmech
.dec
= NULL
;
716 server
->secmech
.enc
= NULL
;
717 server
->secmech
.dec
= NULL
;