Пример #1
0
def get_munki_client_cert_info():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_info = {}
    cert_info['client_cert_path'] = None
    cert_info['client_key_path'] = None
    cert_info['site_urls'] = []

    # get client cert if it exists
    if munkicommon.pref('UseClientCertificate'):
        cert_info['client_cert_path'] = (
            munkicommon.pref('ClientCertificatePath') or None)
        cert_info['client_key_path'] = munkicommon.pref('ClientKeyPath') or None
        if not cert_info['client_cert_path']:
            for name in ['cert.pem', 'client.pem', 'munki.pem']:
                client_cert_path = os.path.join(
                    ManagedInstallDir, 'certs', name)
                if os.path.exists(client_cert_path):
                    cert_info['client_cert_path'] = client_cert_path
                    break
        site_urls = []
        for key in ['SoftwareRepoURL', 'PackageURL', 'CatalogURL',
                    'ManifestURL', 'IconURL', 'ClientResourceURL']:
            url = munkicommon.pref(key)
            if url:
                site_urls.append(url.rstrip('/') + '/')
        cert_info['site_urls'] = site_urls
    return cert_info
Пример #2
0
def get_munki_client_cert_info():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_info = {}
    cert_info['client_cert_path'] = None
    cert_info['client_key_path'] = None
    cert_info['site_urls'] = []

    # get client cert if it exists
    if munkicommon.pref('UseClientCertificate'):
        cert_info['client_cert_path'] = (
            munkicommon.pref('ClientCertificatePath') or None)
        cert_info['client_key_path'] = munkicommon.pref('ClientKeyPath') or None
        if not cert_info['client_cert_path']:
            for name in ['cert.pem', 'client.pem', 'munki.pem']:
                client_cert_path = os.path.join(
                    ManagedInstallDir, 'certs', name)
                if os.path.exists(client_cert_path):
                    cert_info['client_cert_path'] = client_cert_path
                    break
        site_urls = []
        for key in ['SoftwareRepoURL', 'PackageURL', 'CatalogURL',
                    'ManifestURL', 'IconURL', 'ClientResourceURL']:
            url = munkicommon.pref(key)
            if url:
                site_urls.append(url.rstrip('/') + '/')
        cert_info['site_urls'] = site_urls
    return cert_info
Пример #3
0
def get_munki_client_cert_data():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_data = {}

    cert_data['client_cert_path'] = None
    cert_data['client_key_path'] = None
    # get client cert if it exists
    if munkicommon.pref('UseClientCertificate'):
        cert_data['client_cert_path'] = (
            munkicommon.pref('ClientCertificatePath') or None)
        cert_data['client_key_path'] = munkicommon.pref(
            'ClientKeyPath') or None
        if not cert_data['client_cert_path']:
            for name in ['cert.pem', 'client.pem', 'munki.pem']:
                client_cert_path = os.path.join(ManagedInstallDir, 'certs',
                                                name)
                if os.path.exists(client_cert_path):
                    cert_data['client_cert_path'] = client_cert_path
                    break

    cert_data['site_url'] = (munkicommon.pref('SoftwareRepoURL').rstrip('/') +
                             '/')
    return cert_data
Пример #4
0
def download_icons(item_list, icon_dir):
    """Download icons for items in the list.

  Based on updatecheck.py, modified.
  Copied from
  https://github.com/munki/munki/blob/master/code/client/munkilib/updatecheck.py#L2824

  Attempts to download icons (actually png files) for items in
     item_list
  """
    icon_list = []
    icon_known_exts = [
        '.bmp', '.gif', '.icns', '.jpg', '.jpeg', '.png', '.psd', '.tga',
        '.tif', '.tiff', '.yuv'
    ]
    icon_base_url = (pref('IconURL') or pref('SoftwareRepoURL') + '/icons/')
    icon_base_url = icon_base_url.rstrip('/') + '/'
    for item in item_list:
        icon_name = item.get('icon_name') or item['name']
        pkginfo_icon_hash = item.get('icon_hash')
        if not os.path.splitext(icon_name)[1] in icon_known_exts:
            icon_name += '.png'
        icon_list.append(icon_name)
        icon_url = icon_base_url + urllib2.quote(icon_name.encode('UTF-8'))
        icon_path = os.path.join(icon_dir, icon_name)
        if os.path.isfile(icon_path):
            xattr_hash = getxattr(icon_path, XATTR_SHA)
            if not xattr_hash:
                xattr_hash = getsha256hash(icon_path)
                writeCachedChecksum(icon_path, xattr_hash)
        else:
            xattr_hash = 'nonexistent'
        icon_subdir = os.path.dirname(icon_path)
        if not os.path.exists(icon_subdir):
            try:
                os.makedirs(icon_subdir, 0755)
            except OSError, err:
                print 'Could not create %s' % icon_subdir
                continue
        custom_headers = ['']
        if BASIC_AUTH:
            # custom_headers = ['Authorization: Basic %s' % BASIC_AUTH]
            custom_headers = BASIC_AUTH
        if pkginfo_icon_hash != xattr_hash:
            item_name = item.get('display_name') or item['name']
            message = 'Getting icon %s for %s...' % (icon_name, item_name)
            try:
                dummy_value = getResourceIfChangedAtomically(
                    icon_url,
                    icon_path,
                    custom_headers=custom_headers,
                    message=message)
            except MunkiDownloadError, err:
                print('Could not retrieve icon %s from the server: %s',
                      icon_name, err)
            else:
                if os.path.isfile(icon_path):
                    writeCachedChecksum(icon_path)
Пример #5
0
def download_icons(item_list, icon_dir):
  """Download icons for items in the list.

  Based on updatecheck.py, modified.
  Copied from
  https://github.com/munki/munki/blob/master/code/client/munkilib/updatecheck.py#L2824

  Attempts to download icons (actually png files) for items in
     item_list
  """
  icon_list = []
  icon_known_exts = ['.bmp', '.gif', '.icns', '.jpg', '.jpeg', '.png', '.psd',
                     '.tga', '.tif', '.tiff', '.yuv']
  icon_base_url = (pref('IconURL') or
                   pref('SoftwareRepoURL') + '/icons/')
  icon_base_url = icon_base_url.rstrip('/') + '/'
  for item in item_list:
    icon_name = item.get('icon_name') or item['name']
    pkginfo_icon_hash = item.get('icon_hash')
    if not os.path.splitext(icon_name)[1] in icon_known_exts:
      icon_name += '.png'
    icon_list.append(icon_name)
    icon_url = icon_base_url + urllib2.quote(icon_name.encode('UTF-8'))
    icon_path = os.path.join(icon_dir, icon_name)
    if os.path.isfile(icon_path):
      xattr_hash = getxattr(icon_path, XATTR_SHA)
      if not xattr_hash:
        xattr_hash = getsha256hash(icon_path)
        writeCachedChecksum(icon_path, xattr_hash)
    else:
      xattr_hash = 'nonexistent'
    icon_subdir = os.path.dirname(icon_path)
    if not os.path.exists(icon_subdir):
      try:
          os.makedirs(icon_subdir, 0755)
      except OSError, err:
          print 'Could not create %s' % icon_subdir
          continue
    custom_headers = ['']
    if BASIC_AUTH:
      # custom_headers = ['Authorization: Basic %s' % BASIC_AUTH]
      custom_headers = BASIC_AUTH
    if pkginfo_icon_hash != xattr_hash:
      item_name = item.get('display_name') or item['name']
      message = 'Getting icon %s for %s...' % (icon_name, item_name)
      try:
        dummy_value = getResourceIfChangedAtomically(
          icon_url, icon_path, custom_headers=custom_headers, message=message)
      except MunkiDownloadError, err:
        print ('Could not retrieve icon %s from the server: %s',
               icon_name, err)
      else:
        if os.path.isfile(icon_path):
            writeCachedChecksum(icon_path)
Пример #6
0
def handle_custom(custom_dir):
  """Download custom resources and build the package."""
  print "Downloading Munki client resources."
  updatecheck.download_client_resources()
  # Client Resoures are stored in
  #   /Library/Managed Installs/client_resources/custom.zip
  resource_dir = os.path.join(
    pref('ManagedInstallDir'), 'client_resources')
  resource_file = os.path.join(resource_dir, 'custom.zip')
  if os.path.isfile(resource_file):
    destination_path = custom_dir
    pkg_output_file = os.path.join(CACHE, 'munki_custom.pkg')
    success = build_pkg(
      resource_dir,
      'munki_custom',
      'com.facebook.cpe.munki_custom',
      destination_path,
      CACHE,
      'Creating the Munki custom resources package.'
    )
    if success:
      return pkg_output_file
    else:
      print >> sys.stderr, "Failed to build Munki custom resources package!"
      return None
Пример #7
0
def doAdobeInstall(item):
    '''Wrapper to handle all the Adobe installer methods.
    First get the path to the installer dmg. We know
    it exists because installer.py already checked.'''

    managedinstallbase = \
                 munkicommon.pref('ManagedInstallDir')
    itempath = os.path.join(managedinstallbase,
                            'Cache',
                            item["installer_item"])
    installer_type = item.get("installer_type","")
    if installer_type == "AdobeSetup":
        # Adobe CS3/CS4 updater or Adobe CS3 installer
        retcode = runAdobeSetup(itempath)
    elif installer_type == "AdobeUberInstaller":
        # Adobe CS4 installer
        pkgname = item.get("adobe_package_name") or \
                  item.get("package_path","")
        retcode = runAdobeUberTool(itempath, pkgname)
    elif installer_type == "AdobeAcrobatUpdater":
        # Acrobat Pro 9 updater
        retcode = updateAcrobatPro(itempath)
    elif installer_type == "AdobeCS5AAMEEPackage":
        # Adobe CS5 AAMEE package
        retcode = runAdobeCS5AAMEEInstall(itempath)
    elif installer_type == "AdobeCS5PatchInstaller":
        # Adobe CS5 updater
        retcode = runAdobeCS5PatchInstaller(itempath,
                                    copylocal=item.get("copy_local"))
    return retcode
Пример #8
0
def doAdobeRemoval(item):
    '''Wrapper for all the Adobe removal methods'''
    uninstallmethod = item['uninstall_method']
    itempath = ""
    if "uninstaller_item" in item:
        managedinstallbase = munkicommon.pref('ManagedInstallDir')
        itempath = os.path.join(managedinstallbase, 'Cache',
                                item["uninstaller_item"])
        if not os.path.exists(itempath):
            munkicommon.display_error("%s package for %s was "
                                      "missing from the cache."
                                      % (uninstallmethod, item['name']))
            return -1

    if uninstallmethod == "AdobeSetup":
        # CS3 uninstall
        retcode = runAdobeSetup(itempath, uninstalling=True)

    elif uninstallmethod == "AdobeUberUninstaller":
        # CS4 uninstall
        pkgname = item.get("adobe_package_name") or \
                  item.get("package_path","")
        retcode = runAdobeUberTool(itempath, pkgname, uninstalling=True)

    elif uninstallmethod == "AdobeCS5AAMEEPackage":
        # CS5 uninstall. Sheesh. Three releases, three methods.
        adobeInstallInfo = item.get('adobe_install_info')
        retcode = doAdobeCS5Uninstall(adobeInstallInfo)

    if retcode:
        munkicommon.display_error("Uninstall of %s failed." % item['name'])
    return retcode
Пример #9
0
def cacheAppleSUScatalog():
    '''Caches a local copy of the current Apple SUS catalog.'''
    osvers = int(os.uname()[2].split('.')[0])
    munkisuscatalog = munkicommon.pref('SoftwareUpdateServerURL')
    prefs_catalogURL = getSoftwareUpdatePref('CatalogURL')
    if munkisuscatalog:
        # defined in Munki's prefs? use that
        catalogURL = munkisuscatalog
    elif prefs_catalogURL:
        # defined via MCX or
        # in /Library/Preferences/com.apple.SoftwareUpdate.plist
        catalogURL = prefs_catalogURL
    elif osvers == 9:
        # default catalog for Leopard
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-leopard.merged-1.sucatalog'
    elif osvers == 10:
        # default catalog for Snow Leopard
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-leopard-snowleopard.merged-1.sucatalog'
    elif osvers == 11:
        # default catalog for Lion
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-lion-snowleopard-leopard.merged-1.sucatalog.gz'
    else:
        munkicommon.display_error(
            'Can\'t determine Software Update CatalogURL for Darwin '
            'version %s', osvers)
        return -1
    if not os.path.exists(swupdCacheDir(temp=False)):
        try:
            os.makedirs(swupdCacheDir(temp=False))
        except OSError, oserr:
            raise ReplicationError(oserr)
Пример #10
0
def appleSoftwareUpdatesAvailable(forcecheck=False, suppresscheck=False):
    '''Checks for available Apple Software Updates, trying not to hit the SUS
    more than needed'''
    if suppresscheck:
        # typically because we're doing a logout install; if
        # there are no waiting Apple Updates we shouldn't
        # trigger a check for them.
        pass
    elif forcecheck:
        # typically because user initiated the check from
        # Managed Software Update.app
        unused_retcode = checkForSoftwareUpdates(forcecheck=True)
    else:
        # have we checked recently?  Don't want to check with
        # Apple Software Update server too frequently
        now = NSDate.new()
        nextSUcheck = now
        lastSUcheckString = munkicommon.pref('LastAppleSoftwareUpdateCheck')
        if lastSUcheckString:
            try:
                lastSUcheck = NSDate.dateWithString_(lastSUcheckString)
                interval = 24 * 60 * 60
                nextSUcheck = lastSUcheck.dateByAddingTimeInterval_(interval)
            except (ValueError, TypeError):
                pass
        if now.timeIntervalSinceDate_(nextSUcheck) >= 0:
            unused_retcode = checkForSoftwareUpdates(forcecheck=True)
        else:
            unused_retcode = checkForSoftwareUpdates(forcecheck=False)

    if writeAppleUpdatesFile():
        displayAppleUpdateInfo()
        return True
    else:
        return False
Пример #11
0
def cacheAppleSUScatalog():
    '''Caches a local copy of the current Apple SUS catalog.'''
    osvers = int(os.uname()[2].split('.')[0])
    munkisuscatalog = munkicommon.pref('SoftwareUpdateServerURL')
    prefs_catalogURL = getSoftwareUpdatePref('CatalogURL')
    if munkisuscatalog:
        # defined in Munki's prefs? use that
        catalogURL = munkisuscatalog
    elif prefs_catalogURL:
        # defined via MCX or
        # in /Library/Preferences/com.apple.SoftwareUpdate.plist
        catalogURL = prefs_catalogURL
    elif osvers == 9:
        # default catalog for Leopard
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-leopard.merged-1.sucatalog'
    elif osvers == 10:
        # default catalog for Snow Leopard
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-leopard-snowleopard.merged-1.sucatalog'
    elif osvers == 11:
        # default catalog for Lion
        catalogURL = 'http://swscan.apple.com/content/catalogs/others/index-lion-snowleopard-leopard.merged-1.sucatalog.gz'
    else:
        munkicommon.display_error(
            'Can\'t determine Software Update CatalogURL for Darwin '
            'version %s', osvers)
        return -1
    if not os.path.exists(swupdCacheDir(temp=False)):
        try:
            os.makedirs(swupdCacheDir(temp=False))
        except OSError, oserr:
            raise ReplicationError(oserr)
Пример #12
0
def swupdCacheDir(temp=True):
    '''Returns the local cache dir for our Software Update
    mini-cache. The temp cache directory is cleared upon install
    completion. The non-temp is kept.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    if temp:
        return os.path.join(ManagedInstallDir, 'swupd', 'mirror')
    else:
        return os.path.join(ManagedInstallDir, 'swupd')
Пример #13
0
def swupdCacheDir(temp=True):
    '''Returns the local cache dir for our Software Update
    mini-cache. The temp cache directory is cleared upon install
    completion. The non-temp is kept.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    if temp:
        return os.path.join(ManagedInstallDir, 'swupd', 'mirror')
    else:
        return os.path.join(ManagedInstallDir, 'swupd')
Пример #14
0
def make_client_keychain(cert_info=None):
    '''Builds a client cert keychain from existing client certs'''

    if not cert_info:
        # just grab data from Munki's preferences/defaults
        cert_info = get_munki_client_cert_info()

    client_cert_path = cert_info['client_cert_path']
    client_key_path = cert_info['client_key_path']
    site_urls = cert_info['site_urls']
    if not client_cert_path:
        # no client, so nothing to do
        munkicommon.display_debug1(
            'No client cert info provided, '
            'so no client keychain will be created.')
        return
    else:
        munkicommon.display_debug1('Client cert path: %s', client_cert_path)
        munkicommon.display_debug1('Client key path:  %s', client_key_path)

    # to do some of the following options correctly, we need to be root
    # and have root's home.
    # check to see if we're root
    if os.geteuid() != 0:
        munkicommon.display_error(
            'Can\'t make our client keychain unless we are root!')
        return
    # switch HOME if needed to root's home
    original_home = os.environ.get('HOME')
    if original_home:
        os.environ['HOME'] = os.path.expanduser('~root')

    keychain_pass = (
        munkicommon.pref('KeychainPassword') or DEFAULT_KEYCHAIN_PASSWORD)
    abs_keychain_path = get_keychain_path()
    if os.path.exists(abs_keychain_path):
        os.unlink(abs_keychain_path)
    if not os.path.exists(os.path.dirname(abs_keychain_path)):
        os.makedirs(os.path.dirname(abs_keychain_path))
    # create a new keychain
    munkicommon.display_debug1('Creating client keychain...')
    try:
        output = security('create-keychain',
                          '-p', keychain_pass, abs_keychain_path)
        if output:
            munkicommon.display_debug2(output)
    except SecurityError, err:
        munkicommon.display_error(
            'Could not create keychain %s: %s', abs_keychain_path, err)
        if original_home:
            # switch it back
            os.environ['HOME'] = original_home
        return
Пример #15
0
def make_client_keychain(cert_info=None):
    '''Builds a client cert keychain from existing client certs'''

    if not cert_info:
        # just grab data from Munki's preferences/defaults
        cert_info = get_munki_client_cert_info()

    client_cert_path = cert_info['client_cert_path']
    client_key_path = cert_info['client_key_path']
    site_urls = cert_info['site_urls']
    if not client_cert_path:
        # no client, so nothing to do
        munkicommon.display_debug1(
            'No client cert info provided, '
            'so no client keychain will be created.')
        return
    else:
        munkicommon.display_debug1('Client cert path: %s', client_cert_path)
        munkicommon.display_debug1('Client key path:  %s', client_key_path)

    # to do some of the following options correctly, we need to be root
    # and have root's home.
    # check to see if we're root
    if os.geteuid() != 0:
        munkicommon.display_error(
            'Can\'t make our client keychain unless we are root!')
        return
    # switch HOME if needed to root's home
    original_home = os.environ.get('HOME')
    if original_home:
        os.environ['HOME'] = os.path.expanduser('~root')

    keychain_pass = (
        munkicommon.pref('KeychainPassword') or DEFAULT_KEYCHAIN_PASSWORD)
    abs_keychain_path = get_keychain_path()
    if os.path.exists(abs_keychain_path):
        os.unlink(abs_keychain_path)
    if not os.path.exists(os.path.dirname(abs_keychain_path)):
        os.makedirs(os.path.dirname(abs_keychain_path))
    # create a new keychain
    munkicommon.display_debug1('Creating client keychain...')
    try:
        output = security('create-keychain',
                          '-p', keychain_pass, abs_keychain_path)
        if output:
            munkicommon.display_debug2(output)
    except SecurityError, err:
        munkicommon.display_error(
            'Could not create keychain %s: %s', abs_keychain_path, err)
        if original_home:
            # switch it back
            os.environ['HOME'] = original_home
        return
Пример #16
0
def get_munki_server_cert_info():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_info = {}

    # get server CA cert if it exists so we can verify the Munki server
    cert_info['ca_cert_path'] = None
    cert_info['ca_dir_path'] = None
    if munkicommon.pref('SoftwareRepoCAPath'):
        CA_path = munkicommon.pref('SoftwareRepoCAPath')
        if os.path.isfile(CA_path):
            cert_info['ca_cert_path'] = CA_path
        elif os.path.isdir(CA_path):
            cert_info['ca_dir_path'] = CA_path
    if munkicommon.pref('SoftwareRepoCACertificate'):
        cert_info['ca_cert_path'] = munkicommon.pref(
            'SoftwareRepoCACertificate')
    if cert_info['ca_cert_path'] == None:
        ca_cert_path = os.path.join(ManagedInstallDir, 'certs', 'ca.pem')
        if os.path.exists(ca_cert_path):
            cert_info['ca_cert_path'] = ca_cert_path
    return cert_info
Пример #17
0
def get_munki_server_cert_data():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_data = {}

    # get server CA cert if it exists so we can verify the Munki server
    cert_data['ca_cert_path'] = None
    cert_data['ca_dir_path'] = None
    if munkicommon.pref('SoftwareRepoCAPath'):
        CA_path = munkicommon.pref('SoftwareRepoCAPath')
        if os.path.isfile(CA_path):
            cert_data['ca_cert_path'] = CA_path
        elif os.path.isdir(CA_path):
            cert_data['ca_dir_path'] = CA_path
    if munkicommon.pref('SoftwareRepoCACertificate'):
        cert_data['ca_cert_path'] = munkicommon.pref(
            'SoftwareRepoCACertificate')
    if cert_data['ca_cert_path'] == None:
        ca_cert_path = os.path.join(ManagedInstallDir, 'certs', 'ca.pem')
        if os.path.exists(ca_cert_path):
            cert_data['ca_cert_path'] = ca_cert_path
    return cert_data
Пример #18
0
def get_munki_client_cert_data():
    '''Attempt to get information we need from Munki's preferences or
    defaults. Returns a dictionary.'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    cert_data = {}

    cert_data['client_cert_path'] = None
    cert_data['client_key_path'] = None
    # get client cert if it exists
    if munkicommon.pref('UseClientCertificate'):
        cert_data['client_cert_path'] = (
            munkicommon.pref('ClientCertificatePath') or None)
        cert_data['client_key_path'] = munkicommon.pref('ClientKeyPath') or None
        if not cert_data['client_cert_path']:
            for name in ['cert.pem', 'client.pem', 'munki.pem']:
                client_cert_path = os.path.join(
                    ManagedInstallDir, 'certs', name)
                if os.path.exists(client_cert_path):
                    cert_data['client_cert_path'] = client_cert_path
                    break

    cert_data['site_url'] = (
        munkicommon.pref('SoftwareRepoURL').rstrip('/') + '/')
    return cert_data
Пример #19
0
def unlock_and_set_nonlocking(keychain_path):
    '''Unlocks the keychain and sets it to non-locking'''
    keychain_pass = (
        munkicommon.pref('KeychainPassword') or DEFAULT_KEYCHAIN_PASSWORD)
    try:
        output = security(
            'unlock-keychain', '-p', keychain_pass, keychain_path)
        if output:
            munkicommon.display_debug2(output)
    except SecurityError, err:
        # some problem unlocking the keychain.
        munkicommon.display_error(
            'Could not unlock %s: %s.', keychain_path, err)
        # delete it
        try:
            os.unlink(keychain_path)
        except OSError, err:
            munkicommon.display_error(
                'Could not remove %s: %s.', keychain_path, err)
Пример #20
0
def unlock_and_set_nonlocking(keychain_path):
    '''Unlocks the keychain and sets it to non-locking'''
    keychain_pass = (munkicommon.pref('KeychainPassword')
                     or DEFAULT_KEYCHAIN_PASSWORD)
    try:
        output = security('unlock-keychain', '-p', keychain_pass,
                          keychain_path)
        if output:
            munkicommon.display_debug2(output)
    except SecurityError, err:
        # some problem unlocking the keychain.
        munkicommon.display_error('Could not unlock %s: %s.', keychain_path,
                                  err)
        # delete it
        try:
            os.unlink(keychain_path)
        except OSError, err:
            munkicommon.display_error('Could not remove %s: %s.',
                                      keychain_path, err)
Пример #21
0
def handle_custom(custom_dir):
    """Download custom resources and build the package."""
    print "Downloading Munki client resources."
    updatecheck.download_client_resources()
    # Client Resoures are stored in
    #   /Library/Managed Installs/client_resources/custom.zip
    resource_dir = os.path.join(pref('ManagedInstallDir'), 'client_resources')
    resource_file = os.path.join(resource_dir, 'custom.zip')
    if os.path.isfile(resource_file):
        destination_path = custom_dir
        pkg_output_file = os.path.join(CACHE, 'munki_custom.pkg')
        success = build_pkg(resource_dir, 'munki_custom',
                            'com.facebook.cpe.munki_custom', destination_path,
                            CACHE,
                            'Creating the Munki custom resources package.')
        if success:
            return pkg_output_file
        else:
            print >> sys.stderr, "Failed to build Munki custom resources package!"
            return None
Пример #22
0
def get_keychain_path():
    '''Returns an absolute path for our keychain'''
    keychain_name = (munkicommon.pref('KeychainName') or DEFAULT_KEYCHAIN_NAME)
    # If we have an odd path that appears to be all directory and no
    # file name, revert to default filename
    if not os.path.basename(keychain_name):
        keychain_name = DEFAULT_KEYCHAIN_NAME
    # Check to make sure it's just a simple file name, no directory
    # information
    if os.path.dirname(keychain_name):
        # keychain name should be just the filename,
        # so we'll drop down to the base name
        keychain_name = os.path.basename(
            keychain_name).strip() or DEFAULT_KEYCHAIN_NAME
    # Correct the filename to include '.keychain' if not already present
    if not keychain_name.lower().endswith('.keychain'):
        keychain_name += '.keychain'
    keychain_path = os.path.realpath(
        os.path.join(KEYCHAIN_DIRECTORY, keychain_name))
    return keychain_path
Пример #23
0
def installedApplePackagesChanged():
    '''Generates a SHA-256 checksum of the info for all packages in the
    receipts database whose id matches com.apple.* and compares it to
    a stored version of this checksum. Returns False if the checksums
    match, True if they differ.'''
    cmd = ['/usr/sbin/pkgutil', '--regexp', '-pkg-info-plist',
           'com\.apple\.*']
    proc = subprocess.Popen(cmd, shell=False, bufsize=1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (output, unused_err) = proc.communicate()
    current_apple_packages_checksum = hashlib.sha256(output).hexdigest()
    old_apple_packages_checksum = munkicommon.pref(
        'InstalledApplePackagesChecksum')
    if current_apple_packages_checksum == old_apple_packages_checksum:
        return False
    else:
        munkicommon.set_pref('InstalledApplePackagesChecksum',
                             current_apple_packages_checksum)
        return True
Пример #24
0
def get_keychain_path():
    '''Returns an absolute path for our keychain'''
    keychain_name = (
        munkicommon.pref('KeychainName') or DEFAULT_KEYCHAIN_NAME)
    # If we have an odd path that appears to be all directory and no
    # file name, revert to default filename
    if not os.path.basename(keychain_name):
        keychain_name = DEFAULT_KEYCHAIN_NAME
    # Check to make sure it's just a simple file name, no directory
    # information
    if os.path.dirname(keychain_name):
        # keychain name should be just the filename,
        # so we'll drop down to the base name
        keychain_name = os.path.basename(
            keychain_name).strip() or DEFAULT_KEYCHAIN_NAME
    # Correct the filename to include '.keychain' if not already present
    if not keychain_name.lower().endswith('.keychain'):
        keychain_name += '.keychain'
    keychain_path = os.path.realpath(
        os.path.join(KEYCHAIN_DIRECTORY, keychain_name))
    return keychain_path
Пример #25
0
def installedApplePackagesChanged():
    '''Generates a SHA-256 checksum of the info for all packages in the
    receipts database whose id matches com.apple.* and compares it to
    a stored version of this checksum. Returns False if the checksums
    match, True if they differ.'''
    cmd = ['/usr/sbin/pkgutil', '--regexp', '-pkg-info-plist', 'com\.apple\.*']
    proc = subprocess.Popen(cmd,
                            shell=False,
                            bufsize=1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    (output, unused_err) = proc.communicate()
    current_apple_packages_checksum = hashlib.sha256(output).hexdigest()
    old_apple_packages_checksum = munkicommon.pref(
        'InstalledApplePackagesChecksum')
    if current_apple_packages_checksum == old_apple_packages_checksum:
        return False
    else:
        munkicommon.set_pref('InstalledApplePackagesChecksum',
                             current_apple_packages_checksum)
        return True
Пример #26
0
def appleSoftwareUpdatesAvailable(forcecheck=False, suppresscheck=False):
    '''Checks for available Apple Software Updates, trying not to hit the SUS
    more than needed'''
    if suppresscheck:
        # typically because we're doing a logout install; if
        # there are no waiting Apple Updates we shouldn't
        # trigger a check for them.
        pass
    elif forcecheck:
        # typically because user initiated the check from
        # Managed Software Update.app
        unused_retcode = checkForSoftwareUpdates(forcecheck=True)
    else:
        # have we checked recently?  Don't want to check with
        # Apple Software Update server too frequently
        now = NSDate.new()
        nextSUcheck = now
        lastSUcheckString = munkicommon.pref('LastAppleSoftwareUpdateCheck')
        if lastSUcheckString:
            try:
                lastSUcheck = NSDate.dateWithString_(lastSUcheckString)
                interval = 24 * 60 * 60
                nextSUcheck = lastSUcheck.dateByAddingTimeInterval_(interval)
            except (ValueError, TypeError):
                pass
        if now.timeIntervalSinceDate_(nextSUcheck) >= 0:
            unused_retcode = checkForSoftwareUpdates(forcecheck=True)
        else:
            unused_retcode = checkForSoftwareUpdates(forcecheck=False)


    if writeAppleUpdatesFile():
        displayAppleUpdateInfo()
        return True
    else:
        return False
Пример #27
0
def verifySoftwarePackageIntegrity(file_path, item_hash, always_hash=False):
    """Verifies the integrity of the given software package.

    The feature is controlled through the PackageVerificationMode key in
    the ManagedInstalls.plist. Following modes currently exist:
        none: No integrity check is performed.
        hash: Integrity check is performed by calcualting a SHA-256 hash of
            the given file and comparing it against the reference value in
            catalog. Only applies for package plists that contain the
            item_key; for packages without the item_key, verifcation always
            returns True.
        hash_strict: Same as hash, but returns False for package plists that
            do not contain the item_key.

    Args:
        file_path: The file to check integrity on.
        item_hash: the sha256 hash expected.
        always_hash: True/False always check (& return) the hash even if not
                necessary for this function.

    Returns:
        (True/False, sha256-hash)
        True if the package integrity could be validated. Otherwise, False.
    """
    mode = munkicommon.pref('PackageVerificationMode')
    chash = None
    item_name = getURLitemBasename(file_path)
    if always_hash:
        chash = munkicommon.getsha256hash(file_path)

    if not mode:
        return (True, chash)
    elif mode.lower() == 'none':
        munkicommon.display_warning('Package integrity checking is disabled.')
        return (True, chash)
    elif mode.lower() == 'hash' or mode.lower() == 'hash_strict':
        if item_hash:
            munkicommon.display_status_minor('Verifying package integrity...')
            if not chash:
                chash = munkicommon.getsha256hash(file_path)
            if item_hash == chash:
                return (True, chash)
            else:
                munkicommon.display_error(
                    'Hash value integrity check for %s failed.' % item_name)
                return (False, chash)
        else:
            if mode.lower() == 'hash_strict':
                munkicommon.display_error(
                    'Reference hash value for %s is missing in catalog.' %
                    item_name)
                return (False, chash)
            else:
                munkicommon.display_warning(
                    'Reference hash value missing for %s -- package '
                    'integrity verification skipped.' % item_name)
                return (True, chash)
    else:
        munkicommon.display_error(
            'The PackageVerificationMode in the ManagedInstalls.plist has an '
            'illegal value: %s' % munkicommon.pref('PackageVerificationMode'))

    return (False, chash)
Пример #28
0
def appleUpdatesFile():
    '''Returns path to the AppleUpdates.plist'''
    return os.path.join(munkicommon.pref('ManagedInstallDir'),
                        'AppleUpdates.plist')
Пример #29
0
    if minor_os_version > 8:
        # Try to find our ptyexec tool
        # first look in the parent directory of this file's directory
        # (../)
        parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        ptyexec_path = os.path.join(parent_dir, 'ptyexec')
        if not os.path.exists(ptyexec_path):
            # try absolute path in munki's normal install dir
            ptyexec_path = '/usr/local/munki/ptyexec'
        if os.path.exists(ptyexec_path):
            cmd = [ptyexec_path]

    # Workaround for current issue in OS X 10.9's included curl
    # Allows for alternate curl binary path as Apple's included curl currently
    # broken for client-side certificate usage
    curl_path = munkicommon.pref('CurlPath') or '/usr/bin/curl'
    cmd.extend([curl_path,
                '-q',                    # don't read .curlrc file
                '--config',              # use config file
                curldirectivepath])

    proc = subprocess.Popen(cmd, shell=False, bufsize=1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    targetsize = 0
    downloadedpercent = -1
    donewithheaders = False
    maxheaders = 15

    while True:
Пример #30
0
"""

import base64
import hashlib
import os
import subprocess

import munkicommon

# we use lots of camelCase-style names. Deal with it.
# pylint: disable=C0103

DEFAULT_KEYCHAIN_NAME = 'munki.keychain'
DEFAULT_KEYCHAIN_PASSWORD = '******'
KEYCHAIN_DIRECTORY = os.path.join(
    munkicommon.pref('ManagedInstallDir'), 'Keychains')


def read_file(pathname):
    '''Return the contents of pathname as a string'''
    try:
        fileobj = open(pathname, mode='r')
        data = fileobj.read()
        fileobj.close()
        return data
    except (OSError, IOError), err:
        munkicommon.display_error(
            'Could not read %s: %s', pathname, err)
        return ''

Пример #31
0
def appleUpdatesFile():
    '''Returns path to the AppleUpdates.plist'''
    return os.path.join(munkicommon.pref('ManagedInstallDir'),
                                'AppleUpdates.plist')
Пример #32
0
    https://gist.github.com/pudquick/7704254

"""

import os
import re
import subprocess

import munkicommon

# we use lots of camelCase-style names. Deal with it.
# pylint: disable=C0103

DEFAULT_KEYCHAIN_NAME = 'munki.keychain'
DEFAULT_KEYCHAIN_PASSWORD = '******'
KEYCHAIN_DIRECTORY = os.path.join(munkicommon.pref('ManagedInstallDir'),
                                  'Keychains')


def read_file(pathname):
    '''Return the contents of pathname as a string'''
    try:
        fileobj = open(pathname, mode='r')
        data = fileobj.read()
        fileobj.close()
        return data
    except (OSError, IOError), err:
        munkicommon.display_error('Could not read %s: %s', pathname, err)
        return ''

Пример #33
0
"""

import base64
import hashlib
import os
import subprocess

import munkicommon

# we use lots of camelCase-style names. Deal with it.
# pylint: disable=C0103

DEFAULT_KEYCHAIN_NAME = 'munki.keychain'
DEFAULT_KEYCHAIN_PASSWORD = '******'
KEYCHAIN_DIRECTORY = os.path.join(
    munkicommon.pref('ManagedInstallDir'), 'Keychains')


def read_file(pathname):
    '''Return the contents of pathname as a string'''
    try:
        fileobj = open(pathname, mode='r')
        data = fileobj.read()
        fileobj.close()
        return data
    except (OSError, IOError), err:
        munkicommon.display_error(
            'Could not read %s: %s', pathname, err)
        return ''

Пример #34
0
def profile_receipt_data_path():
    '''Returns the path to our installed profile data store'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    return os.path.join(ManagedInstallDir, 'ConfigProfileData.plist')
Пример #35
0
try:
  import FoundationPlist as plistlib
except ImportError:
  print "Using plistlib"
  import plistlib
try:
  from munkicommon import pref, getsha256hash
  import updatecheck
  from fetch import (getURLitemBasename, getResourceIfChangedAtomically,
                     MunkiDownloadError, writeCachedChecksum,
                     getxattr, XATTR_SHA)
  import keychain
except ImportError as err:
  print "Something went wrong! %s" % err

MUNKI_URL = pref('SoftwareRepoURL')
PKGS_URL = MUNKI_URL + '/pkgs'
ICONS_URL = MUNKI_URL + '/icons'
BASIC_AUTH = pref('AdditionalHttpHeaders')
CACHE = '/tmp'


# download functions
def download_url_to_cache(url, cache, force=False):
  """Take a URL and downloads it to a local cache."""
  cache_path = os.path.join(cache, urllib2.unquote(getURLitemBasename(url)))
  custom_headers = ['']
  if BASIC_AUTH:
    # custom_headers = ['Authorization: Basic %s' % BASIC_AUTH]
    custom_headers = BASIC_AUTH
  if force:
Пример #36
0
        if munkicommon.munkistatusoutput:
            time.sleep(2)

    if not listfiles:
        if not noremovereceipts:
            removeReceipts(pkgkeyslist, noupdateapplepkgdb)
        if munkicommon.munkistatusoutput:
            munkistatus.enableStopButton()
            munkicommon.display_status_minor('Package removal complete.')
            time.sleep(2)

    return 0


# some globals
packagedb = os.path.join(munkicommon.pref('ManagedInstallDir'), "b.receiptdb")


def main():
    '''Used when calling removepackages.py directly from the command line.'''
    # command-line options
    parser = optparse.OptionParser()
    parser.set_usage('''Usage: %prog [options] package_id ...''')
    parser.add_option('--forcedeletebundles',
                      '-f',
                      action='store_true',
                      help='Delete bundles even if they aren\'t empty.')
    parser.add_option('--listfiles',
                      '-l',
                      action='store_true',
                      help='List the filesystem objects to be removed, '
Пример #37
0
def getResourceIfChangedAtomically(url,
                                   destinationpath,
                                   custom_headers=None,
                                   expected_hash=None,
                                   message=None,
                                   resume=False,
                                   verify=False,
                                   follow_redirects=False):
    """Gets file from a URL.
       Checks first if there is already a file with the necessary checksum.
       Then checks if the file has changed on the server, resuming or
       re-downloading as necessary.

       If the file has changed verify the pkg hash if so configured.

       Supported schemes are http, https, file.

       Returns True if a new download was required; False if the
       item is already in the local cache.

       Raises a MunkiDownloadError derived class if there is an error."""

    changed = False

    # If we already have a downloaded file & its (cached) hash matches what
    # we need, do nothing, return unchanged.
    if resume and expected_hash and os.path.isfile(destinationpath):
        xattr_hash = getxattr(destinationpath, XATTR_SHA)
        if not xattr_hash:
            xattr_hash = writeCachedChecksum(destinationpath)
        if xattr_hash == expected_hash:
            #File is already current, no change.
            return False
        elif munkicommon.pref('PackageVerificationMode').lower() in [
                'hash_strict', 'hash'
        ]:
            try:
                os.unlink(destinationpath)
            except OSError:
                pass
        munkicommon.log('Cached payload does not match hash in catalog, '
                        'will check if changed and redownload: %s' %
                        destinationpath)
        #continue with normal if-modified-since/etag update methods.

    if follow_redirects != True:
        # If we haven't explicitly said to follow redirect, the preference decides
        follow_redirects = munkicommon.pref('FollowHTTPRedirects')

    url_parse = urlparse.urlparse(url)
    if url_parse.scheme in ['http', 'https']:
        changed = getHTTPfileIfChangedAtomically(
            url,
            destinationpath,
            custom_headers=custom_headers,
            message=message,
            resume=resume,
            follow_redirects=follow_redirects)
    elif url_parse.scheme == 'file':
        changed = getFileIfChangedAtomically(url_parse.path, destinationpath)
    else:
        raise MunkiDownloadError('Unsupported scheme for %s: %s' %
                                 (url, url_parse.scheme))

    if changed and verify:
        (verify_ok, fhash) = verifySoftwarePackageIntegrity(destinationpath,
                                                            expected_hash,
                                                            always_hash=True)
        if not verify_ok:
            try:
                os.unlink(destinationpath)
            except OSError:
                pass
            raise PackageVerificationError()
        if fhash:
            writeCachedChecksum(destinationpath, fhash=fhash)

    return changed
Пример #38
0
def verifySoftwarePackageIntegrity(file_path, item_hash, always_hash=False):
    """Verifies the integrity of the given software package.

    The feature is controlled through the PackageVerificationMode key in
    the ManagedInstalls.plist. Following modes currently exist:
        none: No integrity check is performed.
        hash: Integrity check is performed by calcualting a SHA-256 hash of
            the given file and comparing it against the reference value in
            catalog. Only applies for package plists that contain the
            item_key; for packages without the item_key, verifcation always
            returns True.
        hash_strict: Same as hash, but returns False for package plists that
            do not contain the item_key.

    Args:
        file_path: The file to check integrity on.
        item_hash: the sha256 hash expected.
        always_hash: True/False always check (& return) the hash even if not
                necessary for this function.

    Returns:
        (True/False, sha256-hash)
        True if the package integrity could be validated. Otherwise, False.
    """
    mode = munkicommon.pref('PackageVerificationMode')
    chash = None
    item_name = getURLitemBasename(file_path)
    if always_hash:
        chash = munkicommon.getsha256hash(file_path)

    if not mode:
        return (True, chash)
    elif mode.lower() == 'none':
        munkicommon.display_warning('Package integrity checking is disabled.')
        return (True, chash)
    elif mode.lower() == 'hash' or mode.lower() == 'hash_strict':
        if item_hash:
            munkicommon.display_status_minor('Verifying package integrity...')
            if not chash:
                chash = munkicommon.getsha256hash(file_path)
            if item_hash == chash:
                return (True, chash)
            else:
                munkicommon.display_error(
                    'Hash value integrity check for %s failed.' %
                    item_name)
                return (False, chash)
        else:
            if mode.lower() == 'hash_strict':
                munkicommon.display_error(
                    'Reference hash value for %s is missing in catalog.'
                    % item_name)
                return (False, chash)
            else:
                munkicommon.display_warning(
                    'Reference hash value missing for %s -- package '
                    'integrity verification skipped.' % item_name)
                return (True, chash)
    else:
        munkicommon.display_error(
            'The PackageVerificationMode in the ManagedInstalls.plist has an '
            'illegal value: %s' % munkicommon.pref('PackageVerificationMode'))

    return (False, chash)
Пример #39
0
def getResourceIfChangedAtomically(url, 
                                   destinationpath,
                                   cert_info=None,
                                   custom_headers=None,
                                   expected_hash=None,
                                   message=None, 
                                   resume=False,
                                   verify=False,
                                   follow_redirects=False):
    """Gets file from a URL.
       Checks first if there is already a file with the necessary checksum.
       Then checks if the file has changed on the server, resuming or
       re-downloading as necessary.

       If the file has changed verify the pkg hash if so configured.

       Supported schemes are http, https, file.

       Returns True if a new download was required; False if the
       item is already in the local cache.

       Raises a MunkiDownloadError derived class if there is an error."""

    changed = False

    # If we already have a downloaded file & its (cached) hash matches what
    # we need, do nothing, return unchanged.
    if resume and expected_hash and os.path.isfile(destinationpath):
        xattr_hash = getxattr(destinationpath, XATTR_SHA)
        if not xattr_hash:
            xattr_hash = writeCachedChecksum(destinationpath)
        if xattr_hash == expected_hash:
            #File is already current, no change.
            return False
        elif munkicommon.pref('PackageVerificationMode').lower() in \
                                                    ['hash_strict', 'hash']:
            try:
                os.unlink(destinationpath)
            except OSError:
                pass
        munkicommon.log('Cached payload does not match hash in catalog, '
                'will check if changed and redownload: %s' % destinationpath)
        #continue with normal if-modified-since/etag update methods.

    url_parse = urlparse.urlparse(url)
    if url_parse.scheme in ['http', 'https']:
        changed = getHTTPfileIfChangedAtomically(
            url, destinationpath,
            cert_info=cert_info, custom_headers=custom_headers,
            message=message, resume=resume, follow_redirects=follow_redirects)
    elif url_parse.scheme == 'file':
        changed = getFileIfChangedAtomically(url_parse.path, destinationpath)
    else:
        raise MunkiDownloadError(
                'Unsupported scheme for %s: %s' % (url, url_parse.scheme))

    if changed and verify:
        (verify_ok, fhash) = verifySoftwarePackageIntegrity(destinationpath,
                                                          expected_hash,
                                                          always_hash=True)
        if not verify_ok:
            try:
                os.unlink(destinationpath)
            except OSError:
                pass
            raise PackageVerificationError()
        if fhash:
            writeCachedChecksum(destinationpath, fhash=fhash)

    return changed
Пример #40
0
def get_url(url,
            destinationpath,
            custom_headers=None,
            message=None,
            onlyifnewer=False,
            resume=False,
            follow_redirects=False):
    """Gets an HTTP or HTTPS URL and stores it in
    destination path. Returns a dictionary of headers, which includes
    http_result_code and http_result_description.
    Will raise CurlError if Gurl returns an error.
    Will raise HTTPError if HTTP Result code is not 2xx or 304.
    If destinationpath already exists, you can set 'onlyifnewer' to true to
    indicate you only want to download the file only if it's newer on the
    server.
    If you set resume to True, Gurl will attempt to resume an
    interrupted download."""

    tempdownloadpath = destinationpath + '.download'
    if os.path.exists(tempdownloadpath) and not resume:
        if resume and not os.path.exists(destinationpath):
            os.remove(tempdownloadpath)

    cache_data = None
    if onlyifnewer and os.path.exists(destinationpath):
        # create a temporary Gurl object so we can extract the
        # stored caching data so we can download only if the
        # file has changed on the server
        gurl_obj = Gurl.alloc().initWithOptions_({'file': destinationpath})
        cache_data = gurl_obj.get_stored_headers()
        del gurl_obj

    # only works with NSURLSession (10.9 and newer)
    ignore_system_proxy = munkicommon.pref('IgnoreSystemProxies')

    options = {
        'url': url,
        'file': tempdownloadpath,
        'follow_redirects': follow_redirects,
        'ignore_system_proxy': ignore_system_proxy,
        'can_resume': resume,
        'additional_headers': header_dict_from_list(custom_headers),
        'download_only_if_changed': onlyifnewer,
        'cache_data': cache_data,
        'logging_function': munkicommon.display_debug2
    }
    munkicommon.display_debug2('Options: %s' % options)

    # Allow middleware to modify options
    if middleware:
        munkicommon.display_debug2('Processing options through middleware')
        # middleware module must have process_request_options function
        # and must return usable options
        options = middleware.process_request_options(options)
        munkicommon.display_debug2('Options: %s' % options)

    connection = Gurl.alloc().initWithOptions_(options)
    stored_percent_complete = -1
    stored_bytes_received = 0
    connection.start()
    try:
        while True:
            # if we did `while not connection.isDone()` we'd miss printing
            # messages and displaying percentages if we exit the loop first
            connection_done = connection.isDone()
            if message and connection.status and connection.status != 304:
                # log always, display if verbose is 1 or more
                # also display in MunkiStatus detail field
                munkicommon.display_status_minor(message)
                # now clear message so we don't display it again
                message = None
            if (str(connection.status).startswith('2')
                    and connection.percentComplete != -1):
                if connection.percentComplete != stored_percent_complete:
                    # display percent done if it has changed
                    stored_percent_complete = connection.percentComplete
                    munkicommon.display_percent_done(stored_percent_complete,
                                                     100)
            elif connection.bytesReceived != stored_bytes_received:
                # if we don't have percent done info, log bytes received
                stored_bytes_received = connection.bytesReceived
                munkicommon.display_detail('Bytes received: %s',
                                           stored_bytes_received)
            if connection_done:
                break

    except (KeyboardInterrupt, SystemExit):
        # safely kill the connection then re-raise
        connection.cancel()
        raise
    except Exception, err:  # too general, I know
        # Let us out! ... Safely! Unexpectedly quit dialogs are annoying...
        connection.cancel()
        # Re-raise the error as a GurlError
        raise GurlError(-1, str(err))
Пример #41
0
try:
    import FoundationPlist as plistlib
except ImportError:
    print "Using plistlib"
    import plistlib
try:
    from munkicommon import pref, getsha256hash
    import updatecheck
    from fetch import (getURLitemBasename, getResourceIfChangedAtomically,
                       MunkiDownloadError, writeCachedChecksum, getxattr,
                       XATTR_SHA)
    import keychain
except ImportError as err:
    print "Something went wrong! %s" % err

MUNKI_URL = pref('SoftwareRepoURL')
PKGS_URL = MUNKI_URL + '/pkgs'
ICONS_URL = MUNKI_URL + '/icons'
BASIC_AUTH = pref('AdditionalHttpHeaders')
CACHE = '/tmp'


# download functions
def download_url_to_cache(url, cache, force=False):
    """Take a URL and downloads it to a local cache."""
    cache_path = os.path.join(cache, urllib2.unquote(getURLitemBasename(url)))
    custom_headers = ['']
    if BASIC_AUTH:
        # custom_headers = ['Authorization: Basic %s' % BASIC_AUTH]
        custom_headers = BASIC_AUTH
    if force:
Пример #42
0
        if munkicommon.munkistatusoutput:
            time.sleep(2)

    if not listfiles:
        if not noremovereceipts:
            removeReceipts(pkgkeyslist, noupdateapplepkgdb)
        if munkicommon.munkistatusoutput:
            munkistatus.enableStopButton()
            munkicommon.display_status_minor('Package removal complete.')
            time.sleep(2)

    return 0


# some globals
packagedb = os.path.join(munkicommon.pref('ManagedInstallDir'), "b.receiptdb")

def main():
    '''Used when calling removepackages.py directly from the command line.'''
    # command-line options
    p = optparse.OptionParser()
    p.set_usage('''Usage: %prog [options] package_id ...''')
    p.add_option('--forcedeletebundles', '-f', action='store_true',
                    help='Delete bundles even if they aren\'t empty.')
    p.add_option('--listfiles', '-l', action='store_true',
                    help='''List the filesystem objects to be removed,
                    but do not actually remove them.''')
    p.add_option('--rebuildpkgdb', action='store_true',
                    help='Force a rebuild of the internal package database.')
    p.add_option('--noremovereceipts', action='store_true',
                    help='''Do not remove receipts and boms from
Пример #43
0
def profile_receipt_data_path():
    '''Returns the path to our installed profile data store'''
    ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
    return os.path.join(ManagedInstallDir, 'ConfigProfileData.plist')
Пример #44
0
def get_url(url, destinationpath,
            custom_headers=None, message=None, onlyifnewer=False,
            resume=False, follow_redirects=False):
    """Gets an HTTP or HTTPS URL and stores it in
    destination path. Returns a dictionary of headers, which includes
    http_result_code and http_result_description.
    Will raise GurlError if Gurl returns an error.
    Will raise HTTPError if HTTP Result code is not 2xx or 304.
    If destinationpath already exists, you can set 'onlyifnewer' to true to
    indicate you only want to download the file only if it's newer on the
    server.
    If you set resume to True, Gurl will attempt to resume an
    interrupted download."""

    tempdownloadpath = destinationpath + '.download'
    if os.path.exists(tempdownloadpath) and not resume:
        if resume and not os.path.exists(destinationpath):
            os.remove(tempdownloadpath)

    cache_data = None
    if onlyifnewer and os.path.exists(destinationpath):
        # create a temporary Gurl object so we can extract the
        # stored caching data so we can download only if the
        # file has changed on the server
        gurl_obj = Gurl.alloc().initWithOptions_({'file': destinationpath})
        cache_data = gurl_obj.get_stored_headers()
        del gurl_obj

    # only works with NSURLSession (10.9 and newer)
    ignore_system_proxy = munkicommon.pref('IgnoreSystemProxies')

    options = {'url': url,
               'file': tempdownloadpath,
               'follow_redirects': follow_redirects,
               'ignore_system_proxy': ignore_system_proxy,
               'can_resume': resume,
               'additional_headers': header_dict_from_list(custom_headers),
               'download_only_if_changed': onlyifnewer,
               'cache_data': cache_data,
               'logging_function': munkicommon.display_debug2}
    munkicommon.display_debug2('Options: %s' % options)

    # Allow middleware to modify options
    if middleware:
        munkicommon.display_debug2('Processing options through middleware')
        # middleware module must have process_request_options function
        # and must return usable options
        options = middleware.process_request_options(options)
        munkicommon.display_debug2('Options: %s' % options)

    connection = Gurl.alloc().initWithOptions_(options)
    stored_percent_complete = -1
    stored_bytes_received = 0
    connection.start()
    try:
        while True:
            # if we did `while not connection.isDone()` we'd miss printing
            # messages and displaying percentages if we exit the loop first
            connection_done = connection.isDone()
            if message and connection.status and connection.status != 304:
                # log always, display if verbose is 1 or more
                # also display in MunkiStatus detail field
                munkicommon.display_status_minor(message)
                # now clear message so we don't display it again
                message = None
            if (str(connection.status).startswith('2')
                    and connection.percentComplete != -1):
                if connection.percentComplete != stored_percent_complete:
                    # display percent done if it has changed
                    stored_percent_complete = connection.percentComplete
                    munkicommon.display_percent_done(
                        stored_percent_complete, 100)
            elif connection.bytesReceived != stored_bytes_received:
                # if we don't have percent done info, log bytes received
                stored_bytes_received = connection.bytesReceived
                munkicommon.display_detail(
                    'Bytes received: %s', stored_bytes_received)
            if connection_done:
                break

    except (KeyboardInterrupt, SystemExit):
        # safely kill the connection then re-raise
        connection.cancel()
        raise
    except Exception, err:  # too general, I know
        # Let us out! ... Safely! Unexpectedly quit dialogs are annoying...
        connection.cancel()
        # Re-raise the error as a GurlError
        raise GurlError(-1, str(err))