Example #1
0
void *
Id_AuthGetExternal(size_t *size) // OUT
{
   AuthorizationRef auth;
   AuthorizationExternalForm *ext;

   auth = IdAuthGet();
   if (!auth) {
      return NULL;
   }

   ext = malloc(sizeof *ext);
   if (!ext) {
      Warning("Unable to allocate an AuthorizationExternalForm.\n");

      return NULL;
   }

   if (AuthorizationMakeExternalForm(auth, ext) != errAuthorizationSuccess) {
      Warning("AuthorizationMakeExternalForm() failed.\n");
      free(ext);

      return NULL;
   }

   *size = sizeof *ext;

   return ext;
}
/*! Logs into a target using a specific portal or all portals in the database.
 *  If an argument is supplied for portal, login occurs over the specified
 *  portal.  Otherwise, the daemon will attempt to login over all portals.
 *  @param handle a handle to a daemon connection.
 *  @param authorization an authorization for the right kiSCSIAuthModifyLogin
 *  @param target specifies the target and connection parameters to use.
 *  @param portal specifies the portal to use (use NULL for all portals).
 *  @param statusCode iSCSI response code indicating operation status.
 *  @return an error code indicating whether the operation was successful. */
errno_t iSCSIDaemonLogin(iSCSIDaemonHandle handle,
                         AuthorizationRef authorization,
                         iSCSITargetRef target,
                         iSCSIPortalRef portal,
                         enum iSCSILoginStatusCode * statusCode)
{
    if(handle < 0 || !target || !authorization || !statusCode)
        return EINVAL;

    CFDataRef targetData = iSCSITargetCreateData(target);
    CFDataRef portalData = NULL;

    iSCSIDMsgLoginCmd cmd = iSCSIDMsgLoginCmdInit;
    cmd.authLength = kAuthorizationExternalFormLength;
    cmd.targetLength = (UInt32)CFDataGetLength(targetData);
    cmd.portalLength = 0;

    if(portal) {
        portalData = iSCSIPortalCreateData(portal);
        cmd.portalLength = (UInt32)CFDataGetLength(portalData);
    }
    
    AuthorizationExternalForm authExtForm;
    AuthorizationMakeExternalForm(authorization,&authExtForm);
    
    CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                                     (UInt8*)&authExtForm.bytes,
                                                     kAuthorizationExternalFormLength,
                                                     kCFAllocatorDefault);

    errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,
                                       authData,targetData,portalData,NULL);
    
    if(portal)
        CFRelease(portalData);
    CFRelease(targetData);

    if(error)
        return error;

    iSCSIDMsgLoginRsp rsp;

    if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp))
        return EIO;

    if(rsp.funcCode != kiSCSIDLogin)
        return EIO;

    // At this point we have a valid response, process it
    *statusCode = rsp.statusCode;

    return rsp.errorCode;
}
Example #3
0
EAPOLClientConfigurationRef
EAPOLClientConfigurationCreateInternal(CFAllocatorRef allocator,
				       AuthorizationRef auth)
{
    EAPOLClientConfigurationRef		cfg;

    /* allocate/return an EAPOLClientConfigurationRef */
    cfg = __EAPOLClientConfigurationAllocate(allocator);
    if (cfg == NULL) {
	return (NULL);
    }
    if (auth != NULL) {
	cfg->eap_prefs 
	    = SCPreferencesCreateWithAuthorization(allocator,
						   kPrefsName,
						   kEAPOLClientConfigurationPrefsID,
						   auth);
    }
    else {
	cfg->eap_prefs = SCPreferencesCreate(allocator, kPrefsName,
					     kEAPOLClientConfigurationPrefsID);
    }
    if (cfg->eap_prefs == NULL) {
	goto failed;
    }
    if (auth != NULL) {
	AuthorizationExternalForm *	auth_ext_p;
	OSStatus			status;

	auth_ext_p = malloc(sizeof(*auth_ext_p));
	status = AuthorizationMakeExternalForm(auth, auth_ext_p);
	if (status != errAuthorizationSuccess) {
	    free(auth_ext_p);
	    goto failed;
	}
	cfg->auth_ext_p = auth_ext_p;
    }

    import_profiles(cfg);
    cfg->def_auth_props = copy_def_auth_props(cfg->eap_prefs);
    return (cfg);

 failed:
    my_CFRelease(&cfg);
    return (NULL);

}
/*! Sets or updates a shared secret.
 *  @param handle a handle to a daemon connection.
 *  @param authorization an authorization for the right kiSCSIAuthModifyRights.
 *  @param nodeIQN the node iSCSI qualified name.
 *  @param sharedSecret the secret to set.
 *  @return an error code indicating whether the operating was successful. */
errno_t iSCSIDaemonSetSharedSecret(iSCSIDaemonHandle handle,
                                   AuthorizationRef authorization,
                                   CFStringRef nodeIQN,
                                   CFStringRef sharedSecret)
{
    // Validate inputs
    if(handle < 0 || !authorization || !nodeIQN || !sharedSecret)
        return EINVAL;
    
    AuthorizationExternalForm authExtForm;
    AuthorizationMakeExternalForm(authorization,&authExtForm);
    
    CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                                     (UInt8*)&authExtForm.bytes,
                                                     kAuthorizationExternalFormLength,
                                                     kCFAllocatorDefault);
    
    CFDataRef nodeIQNData = CFStringCreateExternalRepresentation(kCFAllocatorDefault,nodeIQN,kCFStringEncodingASCII,0);
    CFDataRef sharedSecretData = CFStringCreateExternalRepresentation(kCFAllocatorDefault,sharedSecret,kCFStringEncodingASCII,0);
    
    iSCSIDMsgSetSharedSecretCmd cmd = iSCSIDMsgSetSharedSecretCmdInit;
    cmd.authorizationLength = (UInt32)CFDataGetLength(authData);
    cmd.nodeIQNLength = (UInt32)CFDataGetLength(nodeIQNData);
    cmd.secretLength = (UInt32)CFDataGetLength(sharedSecretData);
    
    errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,
                                       authData,nodeIQNData,sharedSecretData,NULL);
    
    if(nodeIQNData)
        CFRelease(nodeIQNData);
    
    if(sharedSecretData)
        CFRelease(sharedSecretData);

    if(error)
        return error;
    
    iSCSIDMsgSetSharedSecretRsp rsp;
    
    if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp))
        return EIO;
    
    if(rsp.funcCode != kiSCSIDSetSharedSecret)
        return EIO;

    return rsp.errorCode;
}
Example #5
0
CFDictionaryRef xpcEngineUpdate(CFTypeRef target, uint flags, CFDictionaryRef context)
{
	Message msg("update");
	// target can be NULL, a CFURLRef, a SecRequirementRef, or a CFNumberRef
	if (target) {
		if (CFGetTypeID(target) == CFNumberGetTypeID())
			xpc_dictionary_set_uint64(msg, "rule", cfNumber<int64_t>(CFNumberRef(target)));
		else if (CFGetTypeID(target) == CFURLGetTypeID())
			xpc_dictionary_set_string(msg, "url", cfString(CFURLRef(target)).c_str());
		else if (CFGetTypeID(target) == SecRequirementGetTypeID()) {
			CFRef<CFDataRef> data;
			MacOSError::check(SecRequirementCopyData(SecRequirementRef(target), kSecCSDefaultFlags, &data.aref()));
			xpc_dictionary_set_data(msg, "requirement", CFDataGetBytePtr(data), CFDataGetLength(data));
		} else
			MacOSError::throwMe(errSecCSInvalidObjectRef);
	}
	xpc_dictionary_set_int64(msg, "flags", flags);
	CFRef<CFMutableDictionaryRef> ctx = makeCFMutableDictionary();
	if (context)
		CFDictionaryApplyFunction(context, copyCFDictionary, ctx);
	AuthorizationRef localAuthorization = NULL;
	if (CFDictionaryGetValue(ctx, kSecAssessmentUpdateKeyAuthorization) == NULL) {	// no caller-provided authorization
		MacOSError::check(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &localAuthorization));
		AuthorizationExternalForm extForm;
		MacOSError::check(AuthorizationMakeExternalForm(localAuthorization, &extForm));
		CFDictionaryAddValue(ctx, kSecAssessmentUpdateKeyAuthorization, CFTempData(&extForm, sizeof(extForm)));
	}
	CFRef<CFDataRef> contextData = makeCFData(CFDictionaryRef(ctx));
	xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData));
	
	msg.send();

	if (localAuthorization)
		AuthorizationFree(localAuthorization, kAuthorizationFlagDefaults);
	
	if (int64_t error = xpc_dictionary_get_int64(msg, "error"))
		MacOSError::throwMe(error);
	
	size_t resultLength;
	const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength);
	return makeCFDictionaryFrom(resultData, resultLength);
}
/*! Semaphore that allows a client exclusive accesss to the property list
 *  that contains iSCSI configuraiton parameters and targets. Forces the provided
 *  preferences object to synchronize with property list on the disk.
 *  @param handle a handle to a daemon connection.
 *  @param authorization an authorization for the right kiSCSIAuthModifyRights
 *  @param preferences the preferences to be synchronized
 *  @return an error code indicating whether the operating was successful. */
errno_t iSCSIDaemonPreferencesIOLockAndSync(iSCSIDaemonHandle handle,
                                            AuthorizationRef authorization,
                                            iSCSIPreferencesRef preferences)
{
    // Validate inputs
    if(handle < 0 || !authorization || !preferences)
        return EINVAL;

    //  Send in authorization and acquire lock
    AuthorizationExternalForm authExtForm;
    AuthorizationMakeExternalForm(authorization,&authExtForm);
    
    CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                                     (UInt8*)authExtForm.bytes,
                                                     kAuthorizationExternalFormLength,
                                                     kCFAllocatorDefault);
    
    iSCSIDMsgPreferencesIOLockAndSyncCmd cmd = iSCSIDMsgPreferencesIOLockAndSyncCmdInit;
    cmd.authorizationLength = (UInt32)CFDataGetLength(authData);
    
    errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,authData,NULL);
    
    if(error)
        return error;
    
    iSCSIDMsgPreferencesIOLockAndSyncRsp rsp;
    
    if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp))
        return EIO;
    
    if(rsp.funcCode != kiSCSIDPreferencesIOLockAndSync)
        return EIO;
    
    if(rsp.errorCode == 0) {
        // Force preferences to synchronize after obtaining lock
        // (this ensures that the client has the most up-to-date preferences data)
        iSCSIPreferencesUpdateWithAppValues(preferences);
    }
    
    return rsp.errorCode;
}
Example #7
0
static AuthorizationRef
IdAuthCreateWithFork(void)
{
   int fds[2] = { -1, -1, };
   pid_t child;
   AuthorizationRef auth = NULL;
   struct {
      Bool success;
      AuthorizationExternalForm ext;
   } data;
   uint8 buf;

   /*
    * XXX One more Apple bug related to thread credentials:
    *     AuthorizationCreate() incorrectly uses process instead of thread
    *     credentials. So for this code to properly work in the VMX for
    *     example, we must do this elaborate fork/handshake dance. Fortunately
    *     this function is only called once very early when a process starts.
    */

   if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
      Warning("%s: socketpair() failed.\n", __func__);
      goto out;
   }

   child = fork();
   if (child < 0) {
      Warning("%s: fork() failed.\n", __func__);
      goto out;
   }

   if (child) {
      size_t rcvd;
      int status;
      pid_t result;

      // Parent: use fds[0]

      // Wait until the child has created its process ref to the auth session.
      for (rcvd = 0; rcvd < sizeof data; ) {
         ssize_t actual;

         actual = read(fds[0], (void *)&data + rcvd, sizeof data - rcvd);
         ASSERT(actual <= sizeof data - rcvd);
         if (actual < 0) {
            ASSERT(errno == EPIPE);
            Warning("%s: parent read() failed because child died.\n",
                    __func__);
            data.success = FALSE;
            break;
         }

         rcvd += actual;
      }

      if (data.success) {
         if (AuthorizationCreateFromExternalForm(&data.ext, &auth)
             != errAuthorizationSuccess) {
            Warning("%s: parent AuthorizationCreateFromExternalForm() "
                    "failed.\n", __func__);
         }
      }

      // Tell the child it can now destroy its process ref to the auth session.
      write(fds[0], &buf, sizeof buf);

      // Reap the child, looping if we get interrupted by a signal.
      do {
         result = waitpid(child, &status, 0);
      } while (result == -1 && errno == EINTR);

      ASSERT_NOT_IMPLEMENTED(result == child);
   } else {
      // Child: use fds[1]

      data.success = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
                                         kAuthorizationFlagDefaults, &auth)
                     == errAuthorizationSuccess;
      if (data.success) {
         data.success = AuthorizationMakeExternalForm(auth, &data.ext)
                        == errAuthorizationSuccess;
         if (!data.success) {
            Warning("%s: child AuthorizationMakeExternalForm() failed.\n",
                    __func__);
         }
      } else {
         Warning("%s: child AuthorizationCreate() failed.\n", __func__);
      }

      // Tell the parent it can now create a process ref to the auth session.
      if (write(fds[1], &data, sizeof data) == sizeof data) {
         /*
          * Wait until the child can destroy its process ref to the auth
          * session.
          */

         for (;;) {
            ssize_t actual = read(fds[1], &buf, sizeof buf);

            ASSERT(actual <= sizeof buf);
            if (actual) {
               break;
            }
         }
      }

      /*
       * This implicitly:
       * o Destroys the child process ref to the Authorization session.
       * o Closes fds[0] and fds[1]
       */

      exit(0);
   }

out:
   close(fds[0]);
   close(fds[1]);

   return auth;
}
Example #8
0
static int				/* O - 0 if available */
					/*     1 if not available */
					/*    -1 error */
cups_local_auth(http_t *http)		/* I - HTTP connection to server */
{
#if defined(WIN32) || defined(__EMX__)
 /*
  * Currently WIN32 and OS-2 do not support the CUPS server...
  */

  return (1);
#else
  int			pid;		/* Current process ID */
  FILE			*fp;		/* Certificate file */
  char			trc[16],	/* Try Root Certificate parameter */
			filename[1024];	/* Certificate filename */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */
#  if defined(HAVE_AUTHORIZATION_H)
  OSStatus		status;		/* Status */
  AuthorizationItem	auth_right;	/* Authorization right */
  AuthorizationRights	auth_rights;	/* Authorization rights */
  AuthorizationFlags	auth_flags;	/* Authorization flags */
  AuthorizationExternalForm auth_extrn;	/* Authorization ref external */
  char			auth_key[1024];	/* Buffer */
  char			buffer[1024];	/* Buffer */
#  endif /* HAVE_AUTHORIZATION_H */


  DEBUG_printf(("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"",
                http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname));

 /*
  * See if we are accessing localhost...
  */

  if (!httpAddrLocalhost(http->hostaddr) &&
      _cups_strcasecmp(http->hostname, "localhost") != 0)
  {
    DEBUG_puts("8cups_local_auth: Not a local connection!");
    return (1);
  }

#  if defined(HAVE_AUTHORIZATION_H)
 /*
  * Delete any previous authorization reference...
  */

  if (http->auth_ref)
  {
    AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
    http->auth_ref = NULL;
  }

  if (!getenv("GATEWAY_INTERFACE") &&
      httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		       auth_key, sizeof(auth_key)))
  {
    status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
				 kAuthorizationFlagDefaults, &http->auth_ref);
    if (status != errAuthorizationSuccess)
    {
      DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)",
		    (int)status, cssmErrorString(status)));
      return (-1);
    }

    auth_right.name        = auth_key;
    auth_right.valueLength = 0;
    auth_right.value       = NULL;
    auth_right.flags       = 0;

    auth_rights.count = 1;
    auth_rights.items = &auth_right;

    auth_flags = kAuthorizationFlagDefaults |
		 kAuthorizationFlagPreAuthorize |
		 kAuthorizationFlagInteractionAllowed |
		 kAuthorizationFlagExtendRights;

    status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
				     kAuthorizationEmptyEnvironment,
				     auth_flags, NULL);
    if (status == errAuthorizationSuccess)
      status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn);

    if (status == errAuthorizationSuccess)
    {
     /*
      * Set the authorization string and return...
      */

      httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn,
		     sizeof(auth_extrn));

      httpSetAuthString(http, "AuthRef", buffer);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));
      return (0);
    }
    else if (status == errAuthorizationCanceled)
      return (-1);

    DEBUG_printf(("9cups_local_auth: AuthorizationCopyRights() returned %d (%s)",
		  (int)status, cssmErrorString(status)));

  /*
   * Fall through to try certificates...
   */
  }
#  endif /* HAVE_AUTHORIZATION_H */

#  if defined(SO_PEERCRED) && defined(AF_LOCAL)
 /*
  * See if we can authenticate using the peer credentials provided over a
  * domain socket; if so, specify "PeerCred username" as the authentication
  * information...
  */

  if (
#    ifdef HAVE_GSSAPI
      _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
#    endif /* HAVE_GSSAPI */
#    ifdef HAVE_AUTHORIZATION_H
      !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		        auth_key, sizeof(auth_key)) &&
#    endif /* HAVE_AUTHORIZATION_H */
      http->hostaddr->addr.sa_family == AF_LOCAL &&
      !getenv("GATEWAY_INTERFACE"))	/* Not via CGI programs... */
  {
   /*
    * Verify that the current cupsUser() matches the current UID...
    */

    struct passwd	*pwd;		/* Password information */
    const char		*username;	/* Current username */

    username = cupsUser();

    if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid())
    {
      httpSetAuthString(http, "PeerCred", username);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));

      return (0);
    }
  }
#  endif /* SO_PEERCRED && AF_LOCAL */

 /*
  * Try opening a certificate file for this PID.  If that fails,
  * try the root certificate...
  */

  pid = getpid();
  snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid);
  if ((fp = fopen(filename, "r")) == NULL && pid > 0)
  {
   /*
    * No certificate for this PID; see if we can get the root certificate...
    */

    DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s",
                  filename, strerror(errno)));

#  ifdef HAVE_GSSAPI
    if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
    {
     /*
      * Kerberos required, don't try the root certificate...
      */

      return (1);
    }
#  endif /* HAVE_GSSAPI */

#  ifdef HAVE_AUTHORIZATION_H
    if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		         auth_key, sizeof(auth_key)))
    {
     /*
      * Don't use the root certificate as a replacement for an authkey...
      */

      return (1);
    }
#  endif /* HAVE_AUTHORIZATION_H */
    if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc,
	                  sizeof(trc)))
    {
     /*
      * Scheduler doesn't want us to use the root certificate...
      */

      return (1);
    }

    snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir);
    fp = fopen(filename, "r");
  }

  if (fp)
  {
   /*
    * Read the certificate from the file...
    */

    char	certificate[33],	/* Certificate string */
		*certptr;		/* Pointer to certificate string */

    certptr = fgets(certificate, sizeof(certificate), fp);
    fclose(fp);

    if (certptr)
    {
     /*
      * Set the authorization string and return...
      */

      httpSetAuthString(http, "Local", certificate);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));

      return (0);
    }
  }

  return (1);
#endif /* WIN32 || __EMX__ */
}
int
mhelperPerformCommand(AuthorizationRef authorizationRef, 
                      const char *helperPath, MAHelperCommand command)
{
  int tohelper[2], fromhelper[2];
  int childStatus = 0;
  int written;
  pid_t pid;
//  char buffer[1024];
  AuthorizationExternalForm extAuth;
  
  // authref --> bytestream
  if (AuthorizationMakeExternalForm(authorizationRef, &extAuth))
    return MAHelperCommandInternalError;
  
  if (pipe(tohelper) < 0)
    return MAHelperCommandInternalError;
  
  if (pipe(fromhelper) < 0)
  {
    close(tohelper[0]);
    close(tohelper[1]);
    return MAHelperCommandInternalError;
  }
  
  if ((pid = fork()) < 0)
  {
    close(tohelper[0]);
    close(tohelper[1]);
    close(fromhelper[0]);
    close(fromhelper[1]);
    return MAHelperCommandInternalError;
  }
  else if (pid == 0)
  {
    char *const envp[] = { NULL };
    
    close(0);
    dup2(tohelper[0], 0);
    close(tohelper[0]);
    close(tohelper[1]);
    
    close(1);
	close(2);
    dup2(fromhelper[1], 1);
    dup2(fromhelper[1], 2);
    close(fromhelper[0]);
    close(fromhelper[1]);
    
    execle(helperPath, helperPath, NULL, envp);
    _exit(MAHelperCommandHelperNotFound);
  }
  signal(SIGPIPE, SIG_IGN);
  
  close(tohelper[0]);
  close(fromhelper[1]);
  
  if (write(tohelper[1], &extAuth, sizeof(extAuth)) != sizeof(extAuth))
  {
    close(tohelper[1]);
    close(fromhelper[0]);
    return MAHelperCommandInternalError;
  }
  
  written= write(tohelper[1], &command, sizeof(MAHelperCommand));
  
  close(tohelper[1]);
  
  
  if (written != sizeof(MAHelperCommand))
  {
    close(fromhelper[0]);
    return MAHelperCommandInternalError;
  }

//  read(fromhelper[0], buffer, 1);

  close(fromhelper[0]);
  
  if (waitpid(pid, &childStatus, 0) != pid)
    return MAHelperCommandInternalError;
  
  if (!WIFEXITED(childStatus))
    return MAHelperCommandInternalError;
  
  return WEXITSTATUS(childStatus);
}
Example #10
0
SCPreferencesRef
SCPreferencesCreateWithOptions(CFAllocatorRef	allocator,
			       CFStringRef	name,
			       CFStringRef	prefsID,
			       AuthorizationRef	authorization,
			       CFDictionaryRef	options)
{
	CFDataRef			authorizationData	= NULL;
	SCPreferencesPrivateRef		prefsPrivate;

	if (options != NULL) {
		if (!isA_CFDictionary(options)) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return NULL;
		}
	}

	if (authorization != NULL) {
		CFMutableDictionaryRef	authorizationDict;
		CFBundleRef		bundle;
		CFStringRef		bundleID	= NULL;

		authorizationDict =  CFDictionaryCreateMutable(NULL,
							       0,
							       &kCFTypeDictionaryKeyCallBacks,
							       &kCFTypeDictionaryValueCallBacks);
#if	!TARGET_OS_IPHONE
		if (authorization != kSCPreferencesUseEntitlementAuthorization) {
			CFDataRef			data;
			AuthorizationExternalForm	extForm;
			OSStatus			os_status;

			os_status = AuthorizationMakeExternalForm(authorization, &extForm);
			if (os_status != errAuthorizationSuccess) {
				SCLog(TRUE, LOG_INFO, CFSTR("_SCHelperOpen AuthorizationMakeExternalForm() failed"));
				_SCErrorSet(kSCStatusInvalidArgument);
				CFRelease(authorizationDict);
				return NULL;
			}

			data = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
			CFDictionaryAddValue(authorizationDict,
					     kSCHelperAuthAuthorization,
					     data);
			CFRelease(data);
		}
#endif

		/* get the application/executable/bundle name */
		bundle = CFBundleGetMainBundle();
		if (bundle != NULL) {
			bundleID = CFBundleGetIdentifier(bundle);
			if (bundleID != NULL) {
				CFRetain(bundleID);
			} else {
				CFURLRef	url;

				url = CFBundleCopyExecutableURL(bundle);
				if (url != NULL) {
					bundleID = CFURLCopyPath(url);
					CFRelease(url);
				}
			}

			if (bundleID != NULL) {
				if (CFEqual(bundleID, CFSTR("/"))) {
					CFRelease(bundleID);
					bundleID = NULL;
				}
			}
		}
		if (bundleID == NULL) {
			bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("Unknown(%d)"), getpid());
		}
		CFDictionaryAddValue(authorizationDict,
				     kSCHelperAuthCallerInfo,
				     bundleID);
		CFRelease(bundleID);

		if (authorizationDict != NULL) {
			_SCSerialize((CFPropertyListRef)authorizationDict,
				     &authorizationData,
				     NULL,
				     NULL);
			CFRelease(authorizationDict);
		}
	}

	prefsPrivate = __SCPreferencesCreate(allocator, name, prefsID, authorizationData, options);
	if (authorizationData != NULL) CFRelease(authorizationData);

	return (SCPreferencesRef)prefsPrivate;
}
Example #11
0
/* Return one of our defined error codes. */
static int
performCommand(AuthorizationRef authorizationRef, MyAuthorizedCommand myCommand)
{
    char path[MAXPATHLEN];
    int comms[2] = {};
    int childStatus = 0;
    int written;
    pid_t pid;
	
    AuthorizationExternalForm extAuth;
	
	if(myDebug) fprintf(stderr, "searching authtool\n");
	
    if (!pathForTool(CFSTR("loader"), path))
    {
        /* The tool could disappear from inside the application's package if a user tries to copy the
		 application.  Currently, the Finder will complain that it doesn't have permission to copy the
		 tool and if the user decides to go ahead with the copy, the application gets copied without
		 the tool inside.  At this point, you should recommend that the user re-install the application. */
        
        if(myDebug) fprintf(stderr, "The authtool could not be found.\n");
        
		//showError_loader();
		
		return kMyAuthorizedCommandInternalError;
    }
    if(myDebug) fprintf(stderr, "authtool found.\n");
	
    /* Turn an AuthorizationRef into an external "byte blob" form so it can be transmitted to the authtool. */
    if (AuthorizationMakeExternalForm(authorizationRef, &extAuth))
        return kMyAuthorizedCommandInternalError;
	
	if(myDebug) fprintf(stderr, "AuthorizationMakeExternalForm done.\n");
    
	/* Create a descriptor pair for interprocess communication. */
    if (pipe(comms))
        return kMyAuthorizedCommandInternalError;
	
	if(myDebug) fprintf(stderr, "pipe done.\n");
	
    switch(pid = fork())
    {
        case 0:	/* Child */
        {            
            char *const envp[] = { NULL };
			
            dup2(comms[0], 0);
            close(comms[0]);
            close(comms[1]);
            execle(path, path, NULL, envp);
            _exit(1);
        }
        case -1: /* an error occured */
            close(comms[0]);
            close(comms[1]);
            return kMyAuthorizedCommandInternalError;
        default: /* Parent */
            break;
    }
	
	if(myDebug) fprintf(stderr, "child done.\n");
	
    /* Parent */
    /* Don't abort the program if write fails. */
    signal(SIGPIPE, SIG_IGN);
    
    /* Close input pipe since we are not reading from client. */
    close(comms[0]);
	
	
    if(myDebug) fprintf(stderr, "Passing child externalized authref.\n");
	
    /* Write the ExternalizedAuthorization to our output pipe. */
    if (write(comms[1], &extAuth, sizeof(extAuth)) != sizeof(extAuth))
    {
        close(comms[1]);
        return kMyAuthorizedCommandInternalError;
    }
	
	if(myDebug) fprintf(stderr, "write done.\n");
	
    if(myDebug) fprintf(stderr, "Passing child command.\n");
	
    /* Write the commands we want to execute to our output pipe */
    written = write(comms[1], &myCommand, sizeof(MyAuthorizedCommand));
    
    /* Close output pipe to notify client we are done. */
    close(comms[1]);
    
    if (written != sizeof(MyAuthorizedCommand))
        return kMyAuthorizedCommandInternalError;
	
	if(myDebug) fprintf(stderr, "written != command done.\n");
	
    /* Wait for the tool to return */
    if (waitpid(pid, &childStatus, 0) != pid)
        return kMyAuthorizedCommandInternalError;
	
	
	if(myDebug) fprintf(stderr, "waitpid done.\n");
	
    if (!WIFEXITED(childStatus))
        return kMyAuthorizedCommandInternalError;
    
	if(myDebug) fprintf(stderr, "wifexited done.\n");
	
	
	
    return WEXITSTATUS(childStatus);
}
Example #12
0
int
mhelperPerformCommand3(AuthorizationRef authorizationRef, 
                       const char *helperPath, MAHelperCommand command,
                       void(*output_callback)(const char*, void*),
                       void *callback_data,
                       int *fdret, char **error_message)
{
  int tohelper[2], fromhelper[2];
  int childStatus;
  int written;
  pid_t pid;
  int rc;
  int sv[2];
  int ok;
  AuthorizationExternalForm extAuth;
  
restart:
    ok= 1;
  childStatus= 0;
  
  if (error_message)
    *error_message= NULL;
  
  // authref --> bytestream
  if (authorizationRef && AuthorizationMakeExternalForm(authorizationRef, &extAuth))
    return MAHelperCommandInternalError;
  
  if (pipe(tohelper) < 0)
    return MAHelperCommandInternalError;
  
  if (pipe(fromhelper) < 0)
  {
    close(tohelper[0]);
    close(tohelper[1]);
    return MAHelperCommandInternalError;
  }
  
  if (fdret)
  {
    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
    {
      close(tohelper[0]);
      close(tohelper[1]);
      close(fromhelper[0]);
      close(fromhelper[1]);
      return MAHelperCommandInternalError;
    }
  }
  
  if ((pid = fork()) < 0)
  {
    if (fdret)
    {
      close(sv[0]);
      close(sv[1]);
    }
    close(tohelper[0]);
    close(tohelper[1]);
    close(fromhelper[0]);
    close(fromhelper[1]);
    return MAHelperCommandInternalError;
  }
  else if (pid == 0)
  {
    char *const envp[] = { NULL };
    char sockfd[32];
    
    if (fdret)
    {
      sprintf(sockfd, "%i", sv[1]);
      close(sv[0]);
    }
    close(0);
    dup2(tohelper[0], 0);
    close(tohelper[0]);
    close(tohelper[1]);
    
    close(1);
    dup2(fromhelper[1], 1);
#ifndef DO_DEBUG
    close(2);
    dup2(fromhelper[1], 2);
#endif
    close(fromhelper[0]);
    close(fromhelper[1]);
    
    if (fdret)
      execle(helperPath, helperPath, sockfd, NULL, envp, NULL);
    else
      execle(helperPath, helperPath, NULL, envp, NULL);
    _exit(MAHelperCommandHelperNotFound);
  }
  signal(SIGPIPE, SIG_IGN);
  
  close(tohelper[0]);
  close(fromhelper[1]);
  if (fdret)
    close(sv[1]);
  
  DEBUG("sending auth...");
  if (write(tohelper[1], &extAuth, sizeof(extAuth)) != sizeof(extAuth))
    ok= 0;
  else
  {
    DEBUG("sending command...");
    written= write(tohelper[1], &command, sizeof(MAHelperCommand));  
    if (written != sizeof(MAHelperCommand))
      ok= 0;
  }
  DEBUG("end sending.");
  if (ok && fdret)
  {
    char buffer[1024];
    
    // helper will send an error message in case of error
    // otherwise, an empty string and the fd later
    DEBUG("reading reply code...");
    *fdret= -1;
    // read reply code 
    if (read(fromhelper[0], buffer, sizeof(buffer)) < 0)
      ok= false;
    else
    {
      DEBUG("reply from helper was '%s'", buffer);
      if (buffer[0])
      {
        if (error_message)
          *error_message= strdup(buffer);
      }
      else
      {
        DEBUG("waiting for fd from socket...");
        // read the fd from the socket to the helper
        if (read_fd(sv[0], buffer, sizeof(buffer), fdret) < 0 || *fdret < 0)
        {
        }
        // this is the file name (not error)
        buffer[sizeof(buffer)-1]= 0;
        if (error_message)
          *error_message= strdup(buffer);
        
        DEBUG("fd arrived %i (%s)", *fdret, buffer);
      }
    }
  }
  
  if (ok && output_callback) 
  {
    char line[1024];
    int count;
    DEBUG("waiting for process to finish");
    while ((rc= waitpid(pid, &childStatus, WNOHANG)) == 0)
    {
      count= read(fromhelper[0], line, sizeof(line));
      if (count > 0)
      {
        line[count]= 0;
        (*output_callback)(line, callback_data);
      }
    }
  }
  else
  {
    DEBUG("waiting for error process to finish");
    rc= waitpid(pid, &childStatus, 0);
  }
  DEBUG("end");
  close(fromhelper[0]);
  if (fdret)
    close(sv[0]);
  close(tohelper[1]);
  
  if (WEXITSTATUS(childStatus) == MAHelperCommandNeedsRestart)
    goto restart;
	
  if (!ok)
    return MAHelperCommandInternalError;
  
  if (rc < 0)
    return MAHelperCommandInternalError;
  
  if (!WIFEXITED(childStatus))
    return MAHelperCommandInternalError;
  
  return WEXITSTATUS(childStatus);
}