Пример #1
0
Файл: netfs.c Проект: B1NG0/cifs
/*
 * SMBNetFsTreeConnectForEnumerateShares
 *
 * When enumerating shares we need a IPC$ tree connection. This is really only 
 * need by the old RAP calls, since the DCE/RPC code will create a whole new
 * session.
 */
int32_t
SMBNetFsTreeConnectForEnumerateShares(SMBHANDLE inConnection)
{
	int error = 0;
    void *hContext = NULL;
	
	SMBServerContext(inConnection, &hContext);
	error = smb_ctx_setshare(hContext, "IPC$");
	if (!error) {
		error = smb_share_connect(hContext);
	}
	return error;
}
Пример #2
0
static int
GetRootShareConnection(struct smb_ctx *ctx, const char *url, uint32_t authFlags,
                       const char * clientPrincipal, uint32_t clientNameType,
                       uint32_t	maxTimer)
{
    CFDictionaryRef serverParams = NULL;
    CFDictionaryRef sessionInfo = NULL;
    CFMutableDictionaryRef openOptions;
    int error = 0;
    time_t  start_time = time(NULL);

    openOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
    if (!openOptions) {
        smb_log_info("%s: Couldn't create open options for %s", ASL_LEVEL_ERR,
                     __FUNCTION__, url);
        error = ENOMEM;
        goto done;
    }

#ifdef SMBDEBUG_REMOUNT
    /* This is only needed for testing and should be remove once we have autofs hooked up */
    CFDictionarySetValue(openOptions, kNetFSForceNewSessionKey, kCFBooleanTrue);
#endif // SMBDEBUG_REMOUNT

    /* Never touch the user home directory */
    CFDictionarySetValue(openOptions, kNetFSNoUserPreferencesKey, kCFBooleanTrue);
    /*
     * If they have a loopback in the referral we always allow it, no way for
     * us to decided what is correct at this point.
     */
    CFDictionarySetValue(openOptions, kNetFSAllowLoopbackKey, kCFBooleanTrue);

    /*
     * Do a get server info call first to determine the if the server supports
     * the security we need. Also needed it to make sure we have the correct
     * server principal name.
     */
    while (difftime(time(NULL), start_time) < maxTimer ) {
        error = smb_get_server_info(ctx, NULL, openOptions, &serverParams);
        if (!error) {
            break;
        }
        smb_log_info("%s: get server info failed %d, sleeping one second, have %d seconds left.",
                     ASL_LEVEL_DEBUG,  __FUNCTION__, error,
                     maxTimer - (int)difftime(time(NULL), start_time));
        sleep(1);	/* Wait one second before trying again */
    }
    if (error) {
        smb_log_info("%s: get server info failed from %s with %d",
                     ASL_LEVEL_ERR,  __FUNCTION__, url, error);
        goto done;
    }

    /*
     * We should check the server params and make sure this server supports
     * the same auth method as the old server. Doesn't really make any difference
     * we should fail in the open if they don't support the correct auth.
     */

    /*
     * Set up the authorization using the same auth method that was use in the
     * original mount.
     */
    if (authFlags & (SMBV_GUEST_ACCESS | SMBV_SFS_ACCESS | SMBV_PRIV_GUEST_ACCESS)) {
        CFDictionarySetValue( openOptions, kNetFSUseGuestKey, kCFBooleanTrue);
    } else {
        CFMutableDictionaryRef authInfoDict;

        authInfoDict = CreateAuthDictionary(ctx, authFlags, clientPrincipal, clientNameType);
        if (!authInfoDict) {
            smb_log_info("%s: Creating authorization dictionary failed for  %s",
                         ASL_LEVEL_ERR, __FUNCTION__, url);
            error = ENOMEM;
            goto done;
        }
        CFDictionarySetValue( openOptions, kNetFSUseAuthenticationInfoKey, kCFBooleanTrue);
        CFDictionarySetValue(openOptions, kNetFSAuthenticationInfoKey, authInfoDict);
        CFRelease(authInfoDict);
    }

    error = smb_open_session(ctx, NULL, openOptions, &sessionInfo);
    if (error) {
        smb_log_info("%s: open session failed from url %s with %d", ASL_LEVEL_ERR,
                     __FUNCTION__, url, error);
        goto done;
    }
    error = smb_share_connect(ctx);
    if (error) {
        smb_log_info("%s: share connect failed from url %s with %d", ASL_LEVEL_ERR,
                     __FUNCTION__, url, error);
        goto done;
    }
done:
    if (sessionInfo) {
        CFRelease(sessionInfo);
    }
    if (serverParams) {
        CFRelease(serverParams);
    }
    if (openOptions) {
        CFRelease(openOptions);
    }
    return error;
}
Пример #3
0
NTSTATUS
SMBOpenServerWithMountPoint(
	const char * pTargetMountPath,
	const char * pTargetTreeName,
	SMBHANDLE * outConnection,
	uint64_t    options)
{
	NTSTATUS	status;
	int         err;
	void *      hContext;
	struct statfs statbuf;
		
	*outConnection = NULL;
	
	status = SMBLibraryInit();
	if (!NT_SUCCESS(status)) {
		goto done;
	}
	
	/* Need to get the mount from name, use that as the URL */
	err = statfs(pTargetMountPath, &statbuf);
	if (err) {
		status = STATUS_OBJECT_PATH_NOT_FOUND;
		goto done;
	}
	
	status = SMBAllocateServer(outConnection, statbuf.f_mntfromname);
	if (!NT_SUCCESS(status)) {
		goto done;
	}

	status = SMBServerContext(*outConnection, &hContext);
	if (!NT_SUCCESS(status)) {
		goto done;
	}

	/* Need to clear out the user name field */
	smb_ctx_setuser(hContext, "");
	err = findMountPointVC(hContext, pTargetMountPath);
	if (err) {
		status = STATUS_OBJECT_NAME_NOT_FOUND;
		errno = err;
		goto done;
    }

	if (options & kSMBOptionSessionOnly) {
		goto done;
	}
	
	/*  No tree name, let's assume that the caller means IPC$ */
	if (!pTargetTreeName) {
		pTargetTreeName = "IPC$";
	}
	err = smb_ctx_setshare(hContext, pTargetTreeName);
	if (err) {
		if (err == ENAMETOOLONG) {
			status = STATUS_NAME_TOO_LONG;
		} else {
			status = STATUS_NO_MEMORY;
		}
		errno = err;
		goto done;
	}
	
	/* OK, now we have a virtual circuit but no tree connection yet. */
	err = smb_share_connect((*outConnection)->context);
	if (err) {
		status = STATUS_BAD_NETWORK_NAME;
		errno = err;
		goto done;
	}
	
	status = STATUS_SUCCESS;
	
done:
	if ((!NT_SUCCESS(status)) && *outConnection) {
		SMBReleaseServer(*outConnection);
		*outConnection = NULL;
	}

	return status;
}
Пример #4
0
NTSTATUS 
SMBOpenServerEx(
    const char * targetServer,
    SMBHANDLE * outConnection,
    uint64_t    options)
{
    NTSTATUS    status;
    int         err;
    void *      hContext;

    CFMutableDictionaryRef netfsOptions = NULL;
	CFDictionaryRef ServerParams = NULL;

    *outConnection = NULL;

    status = SMBLibraryInit();
	if (!NT_SUCCESS(status)) {
        goto done;
    }

    netfsOptions = SMBCreateDefaultOptions(options);
    if (netfsOptions == NULL) {
        status = STATUS_NO_MEMORY;
        goto done;
    }

    status = SMBAllocateServer(outConnection, targetServer);
	if (!NT_SUCCESS(status)) {
        goto done;
    }

    status = SMBServerContext(*outConnection, &hContext);
	if (!NT_SUCCESS(status)) {
        goto done;
    }
	
	err = smb_get_server_info(hContext, NULL, netfsOptions, &ServerParams);
	if (err) {
        /* XXX map real NTSTATUS code */
        status = STATUS_CONNECTION_REFUSED;
		errno = err;
		goto done;
    }
	/*
	 * They didn't set the force new session option and we have a shared session,
	 * then we are done. We have a connection and we are authenticated.
	 */
	if (!(options & kSMBOptionForceNewSession) && (((struct smb_ctx *)hContext)->ct_vc_shared)) {
		goto authDone;
	}
	/*
	 * They have guest as the username in the url, then they want us to 
	 * force guest access.
	 */
	if (((struct smb_ctx *)hContext)->ct_setup.ioc_userflags & SMBV_GUEST_ACCESS) {
		options |= kSMBOptionUseGuestOnlyAuth;
	}
	
	/* Connect using Guest Access only */
	if (options & kSMBOptionUseGuestOnlyAuth) {
		status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeGuest);
		goto authDone;
	}

	/* Connect using Anonymous Access only  */
	if (options & kSMBOptionUseAnonymousOnlyAuth) {
		status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAnonymous);
		goto authDone;
	}
	
	/* Attempt an authenticated connect, could be kerberos or ntlm. */
	status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAuthenticated);
	if (NT_SUCCESS(status)) {
		goto authDone;
	}
	
	/* See if we need to prompt for a password */
	if (SMBPasswordPrompt(*outConnection, options)) {
		/* Attempt an authenticated connect again , could be kerberos or ntlm. */
		status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAuthenticated);
		if (NT_SUCCESS(status)) {
			goto authDone;
		}
	}

	/* Kerberos and NTLM failed, attempt Guest access if option set */
	if (options & kSMBOptionAllowGuestAuth) {
		status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeGuest);
		if (NT_SUCCESS(status)) {
			goto authDone;
		}
	}
	
	/* Kerberos and NTLM failed, attempt Anonymous access if option set */
	if (options & kSMBOptionAllowAnonymousAuth) {
		status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAnonymous);
		if (NT_SUCCESS(status)) {
			goto authDone;
		}
	}

authDone:

	if (!NT_SUCCESS(status)) {
		goto done;
	}
		
	if (options & kSMBOptionSessionOnly) {
		goto done;
	}
	
    /* 
	 * If the target doesn't contain a share name, let's assume that the
     * caller means IPC$, unless a share name is required.
     */
    if (!((struct smb_ctx *)hContext)->ct_origshare) {
        err = smb_ctx_setshare(hContext, "IPC$");
        if (err) {
			if (err == ENAMETOOLONG) {
				status = STATUS_NAME_TOO_LONG;
			} else {
				status = STATUS_NO_MEMORY;
			}
			errno = err;
            goto done;
        }
    }
	
    /* OK, now we have a virtual circuit but no tree connection yet. */
    err = smb_share_connect((*outConnection)->context);
    if (err) {
        status = STATUS_BAD_NETWORK_NAME;
		errno = err;
        goto done;
    }
    
    status = STATUS_SUCCESS;

done:
    if (netfsOptions) {
        CFRelease(netfsOptions);
    }
	if (ServerParams) {
		CFRelease(ServerParams);
	}
    if ((!NT_SUCCESS(status)) && *outConnection) {
        SMBReleaseServer(*outConnection);
        *outConnection = NULL;
    }

    return status;
}