Mount SMB share via attaching to StdIn & StdOut of child process

Hello!


I try to read stdout and to write to stdin of a child process using method described here: http://www.microhowto.info/howto/capture_the_output_of_a_child_process_in_c.html


It's work fine for typical commandline tools, but it doesn't work for mount utility - password prompt everytime showed in my (parent) process. Why it happens? What is the difference between typical writing to stdout and password prompting in macOS?


Thanks

Accepted Reply

Some tasks require a pseudo-terminal. They are a bit more tricky to setup than normal child processes. I don't know if the mount command, or any command that has a Terminal password prompt, uses a pseudo-terminal or not. I really don't know what the password mechanism is. I do know that it would not be a good idea to attempt to automate that. It was designed not to be automated. If you succeed, then your success would be a bug that Apple would like to fix. It's just a high-risk approach. Don't go there.


However, while mount is a privileged process, there are other ways to mount volumes. One method I'ved used in the past is NetFSMountURLAsync in the NetFS.h API. It isn't documented anywhere, but it even works from the sandbox.


What are you trying to mount anyway? I would advise against making this a core feature of your product. Mounting external volumes is Apple code. It is also not reliable. You could get very deep into this project and realize some silly Apple bug makes your entire app non-viable. You can't fix Apple code. And when you are deep into a wasteland like this, Apple won't fix it either.

Replies

Mounting a volume is a privileged process on MacOS, and requires that you authenticate yourself to the system, just like sudo.

Some tasks require a pseudo-terminal. They are a bit more tricky to setup than normal child processes. I don't know if the mount command, or any command that has a Terminal password prompt, uses a pseudo-terminal or not. I really don't know what the password mechanism is. I do know that it would not be a good idea to attempt to automate that. It was designed not to be automated. If you succeed, then your success would be a bug that Apple would like to fix. It's just a high-risk approach. Don't go there.


However, while mount is a privileged process, there are other ways to mount volumes. One method I'ved used in the past is NetFSMountURLAsync in the NetFS.h API. It isn't documented anywhere, but it even works from the sandbox.


What are you trying to mount anyway? I would advise against making this a core feature of your product. Mounting external volumes is Apple code. It is also not reliable. You could get very deep into this project and realize some silly Apple bug makes your entire app non-viable. You can't fix Apple code. And when you are deep into a wasteland like this, Apple won't fix it either.

I need mounted SMB shares from user. To make sure SMB are always mounted when I need, I want to mount them myself. So, I ask password from User and try to mount SMB share via my daemon (working by root user).


I tried to use nsmb.conf, but it doesn't work. In manual pages of written:


-NDo not ask for a password. At run time, mount_smbfs reads the ~/Library/Preferences/nsmb.conf file for additional configuration parameters and a password. If no password is found, mount_smbfs prompts for it.


but here are all parameters of nsmb.conf described in manual pages of nsmb.conf:

Possible keywords may include:


KeywordSectionDefaultComment
A B CValues
addr- + - DNS name or IP address of server
nbtimeout+ + -1sTimeout for resolving a NetBIOS name
minauth+ + -NTLMv2Minimum authentication level allowed
port445+ + -bothHow to use SMB TCP/UDP ports
streams+ + +yesUse NTFS Streams if server supported
soft+ + + Make the mount soft
notify_off+ + +noTurn off using notifications
kloglevel+ - -0Turn on smb kernel logging
protocol_vers_map + - -7Bitmap of SMB Versions that are enabled
signing_required+ - -noTurn on smb client signing
signing_req_vers+ - -6Bitmap of SMB Versions that have signing required
validate_neg_off+ - -noTurn off using validate negotiate
max_resp_timeout+ + -30sMax time to wait for any response from server
submounts_off+ + +noTurn off using submounts
dir_cache_async_cnt + + -10Max async queries to fill dir cache
dir_cache_max+ + -60sMax time to cache for a dir
dir_cache_min+ + -30sMin time to cache for a dir


So, threre is not parameter "password", maybe therefore it doesn't work


NetFSMountURLAsync and NetFSMountURLSync from NetFS.framework it's exactly what I need, thanks a lot!


/*
* Given a URL that refers to a file server, connect to that server
* and mount stuff.
*
* If the URL just specifies a server and you can't just mount the
* "root directory" of the server, the user will be prompted with
* a window to let them select one or more items to mount from that
* server, otherwise whatever item the URL specifies to mount will
* be mounted.
*
* If the mountpath is provided it will be used as the mount point.
* If the mountpath is set to NULL, a default mount point will be used.
*
* If the user and passwd are set, they will override any user name
* or password that may be set in the URL. These calls go through the NetAuth agent.
* If the URL doesn't specify a password, and one is needed, the
* user will be prompted with a window requesting password.
*
* Options can be provided for the session open and the mount itself.
* If the mount is successful, the POSIX path to each mountpoint is
* returned as a CFStringRef in mountpoints.
*
* If the return value is zero the mount has succeeded.
*
* A positive non-zero return value represents an errno value
* (see /usr/include/sys/errno.h).  For instance, a missing mountpoint
* error will be returned as ENOENT (2).
*
* A negative non-zero return value represents an OSStatus error.
* For instance, error -128 is userCanceledErr, returned when a mount
* operation is canceled by the user. These OSStatus errors are
* extended to include:
*
*  from this header:
*      ENETFSPWDNEEDSCHANGE            -5045
*      ENETFSPWDPOLICY                 -5046
*      ENETFSACCOUNTRESTRICTED         -5999
*      ENETFSNOSHARESAVAIL             -5998
*      ENETFSNOAUTHMECHSUPP            -5997
*      ENETFSNOPROTOVERSSUPP           -5996
*
*  from 
*      kNetAuthErrorInternal           -6600
*      kNetAuthErrorMountFailed        -6602
*      kNetAuthErrorNoSharesAvailable  -6003
*      kNetAuthErrorGuestNotSupported  -6004
*      kNetAuthErrorAlreadyClosed      -6005
*
*/
NETFS_EXPORT int
NetFSMountURLSync(
        CFURLRef url,                           // URL to mount, e.g. nfs://server/path
        CFURLRef mountpath,                     // Path for the mountpoint
        CFStringRef user,                       // Auth user name (overrides URL)
        CFStringRef passwd,                     // Auth password (overrides URL)
        CFMutableDictionaryRef open_options,    // Options for session open (see below)
        CFMutableDictionaryRef mount_options,   // Options for mounting (see below)
        CFArrayRef *mountpoints)                // Array of mountpoints
        __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA);


I checked NetFSMountURLSync works, thanks!