Esempio n. 1
0
File: sess.c Progetto: 274914765/C
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
                 struct cifsSesInfo *ses,
                 const struct nls_table *nls_cp)
{
    int rc = 0;
    int words_left, len;
    char *data = *pbcc_area;



    cFYI(1, ("bleft %d", bleft));


    /* SMB header is unaligned, so cifs servers word align start of
       Unicode strings */
    data++;
    bleft--; /* Windows servers do not always double null terminate
            their final Unicode string - in which case we
            now will not attempt to decode the byte of junk
            which follows it */

    words_left = bleft / 2;

    /* save off server operating system */
    len = UniStrnlen((wchar_t *) data, words_left);

/* We look for obvious messed up bcc or strings in response so we do not go off
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
    if (len >= words_left)
        return rc;

    kfree(ses->serverOS);
    /* UTF-8 string will not grow more than four times as big as UCS-16 */
    ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
    if (ses->serverOS != NULL)
        cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
    data += 2 * (len + 1);
    words_left -= len + 1;

    /* save off server network operating system */
    len = UniStrnlen((wchar_t *) data, words_left);

    if (len >= words_left)
        return rc;

    kfree(ses->serverNOS);
    ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
    if (ses->serverNOS != NULL) {
        cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
                   nls_cp);
        if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
            cFYI(1, ("NT4 server"));
            ses->flags |= CIFS_SES_NT4;
        }
    }
    data += 2 * (len + 1);
    words_left -= len + 1;

    /* save off server domain */
    len = UniStrnlen((wchar_t *) data, words_left);

    if (len > words_left)
        return rc;

    kfree(ses->serverDomain);
    ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
    if (ses->serverDomain != NULL) {
        cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
                   nls_cp);
        ses->serverDomain[2*len] = 0;
        ses->serverDomain[(2*len) + 1] = 0;
    }
    data += 2 * (len + 1);
    words_left -= len + 1;

    cFYI(1, ("words left: %d", words_left));

    return rc;
}
Esempio n. 2
0
/* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst,
	char *current_entry, __u16 level, unsigned int unicode,
	struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
{
	int rc = 0;
	unsigned int len = 0;
	char *filename;
	struct nls_table *nlt = cifs_sb->local_nls;

	*pinum = 0;

	if (level == SMB_FIND_FILE_UNIX) {
		FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;

		filename = &pFindData->FileName[0];
		if (unicode) {
			len = cifs_unicode_bytelen(filename);
		} else {
			/* BB should we make this strnlen of PATH_MAX? */
			len = strnlen(filename, PATH_MAX);
		}

		*pinum = pFindData->UniqueId;
	} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
		FILE_DIRECTORY_INFO *pFindData =
			(FILE_DIRECTORY_INFO *)current_entry;
		filename = &pFindData->FileName[0];
		len = le32_to_cpu(pFindData->FileNameLength);
	} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
		FILE_FULL_DIRECTORY_INFO *pFindData =
			(FILE_FULL_DIRECTORY_INFO *)current_entry;
		filename = &pFindData->FileName[0];
		len = le32_to_cpu(pFindData->FileNameLength);
	} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
		SEARCH_ID_FULL_DIR_INFO *pFindData =
			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
		filename = &pFindData->FileName[0];
		len = le32_to_cpu(pFindData->FileNameLength);
		*pinum = pFindData->UniqueId;
	} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
		FILE_BOTH_DIRECTORY_INFO *pFindData =
			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
		filename = &pFindData->FileName[0];
		len = le32_to_cpu(pFindData->FileNameLength);
	} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
		FIND_FILE_STANDARD_INFO *pFindData =
			(FIND_FILE_STANDARD_INFO *)current_entry;
		filename = &pFindData->FileName[0];
		/* one byte length, no name conversion */
		len = (unsigned int)pFindData->FileNameLength;
	} else {
		cFYI(1, ("Unknown findfirst level %d", level));
		return -EINVAL;
	}

	if (len > max_len) {
		cERROR(1, ("bad search response length %d past smb end", len));
		return -EINVAL;
	}

	if (unicode) {
		/* BB fixme - test with long names */
		/* Note converted filename can be longer than in unicode */
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
			pqst->len = cifs_convertUCSpath((char *)pqst->name,
					(__le16 *)filename, len/2, nlt);
		else
			pqst->len = cifs_strfromUCS_le((char *)pqst->name,
					(__le16 *)filename, len/2, nlt);
	} else {
		pqst->name = filename;
		pqst->len = len;
	}
	pqst->hash = full_name_hash(pqst->name, pqst->len);
/*	cFYI(1, ("filldir on %s",pqst->name));  */
	return rc;
}
Esempio n. 3
0
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
				 struct cifsSesInfo *ses,
				 const struct nls_table *nls_cp)
{
	int rc = 0;
	int words_left, len;
	char *data = *pbcc_area;

	cFYI(1, ("bleft %d", bleft));

	/*
	 * Windows servers do not always double null terminate their final
	 * Unicode string. Check to see if there are an uneven number of bytes
	 * left. If so, then add an extra NULL pad byte to the end of the
	 * response.
	 *
	 * See section 2.7.2 in "Implementing CIFS" for details
	 */
	if (bleft % 2) {
		data[bleft] = 0;
		++bleft;
	}

	words_left = bleft / 2;

	/* save off server operating system */
	len = UniStrnlen((wchar_t *) data, words_left);

	if (len >= words_left)
		return rc;

	kfree(ses->serverOS);
	/* UTF-8 string will not grow more than four times as big as UCS-16 */
	ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
	if (ses->serverOS != NULL)
		cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
	data += 2 * (len + 1);
	words_left -= len + 1;

	/* save off server network operating system */
	len = UniStrnlen((wchar_t *) data, words_left);

	if (len >= words_left)
		return rc;

	kfree(ses->serverNOS);
	ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
	if (ses->serverNOS != NULL) {
		cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
				   nls_cp);
		if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
			cFYI(1, ("NT4 server"));
			ses->flags |= CIFS_SES_NT4;
		}
	}
	data += 2 * (len + 1);
	words_left -= len + 1;

	/* save off server domain */
	len = UniStrnlen((wchar_t *) data, words_left);

	if (len > words_left)
		return rc;

	kfree(ses->serverDomain);
	ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL);
	if (ses->serverDomain != NULL)
		cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
				   nls_cp);
	data += 2 * (len + 1);
	words_left -= len + 1;

	cFYI(1, ("words left: %d", words_left));

	return rc;
}