delete individual keychain item

icemobile
New Contributor II

I have a situation where i need to deploy a new printer. no problem there!
only problem is user needs to authenticate trough AD printserver.
this means there is a network password in the users keychain named printerc0(x). does any of you know how to remove this individual item trough a script.

im looking into the security command but have trouble singling out the exact item see below.

security dump-keychain ~/Library/Keychains/login.keychain

part of the output i'm interested in:
keychain: "/Users/ben/Library/Keychains/login.keychain"
class: "inet"
attributes: 0x00000007 <blob>="printerc02" 0x00000008 <blob>=<NULL> "acct"<blob>="ben" "atyp"<blob>=<NULL> "cdat"<timedate>=0x32303133303532313134303734325A00 "20130521140742Z�00" "crtr"<uint32>=<NULL> "cusi"<sint32>=<NULL> "desc"<blob>="Network Password" "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"<timedate>=0x32303133303532313134303734325A00 "20130521140742Z�00" "nega"<sint32>=<NULL> "path"<blob>=<NULL> "port"<uint32>=0x00000000 "prot"<blob>=<NULL> "ptcl"<uint32>="smb " "scrp"<sint32>=<NULL> "sdmn"<blob>=<NULL> "srvr"<blob>="ICE2.ice.local" "type"<uint32>=<NULL>

any help is much appreciated

19 REPLIES 19

mm2270
Legendary Contributor II

A network password in the login.keychain would likely be listed as an "internet-password" by security. Try running something like this to locate the one in question:

security find-internet-password -l "printerc0(x)"

The -l flag tells security to search using the label, meaning the name that shows in Keychain Access.
Once you confirm you can see it, you should be able to use the "delete-internet-password" verb in security for this.

security delete-internet-password -l "printerc0(x)"

However, you'd need to specify a user's login.keychain in the above if running it from a policy of course since it would be looking in your service account's keychain by default. That would be the case for both commands.

security delete-internet-password -l "printerc0(x)" /Users/username/Library/Keychains/login.keychain

Hope that helps point you in the right direction.

Edit: Actually, in thinking about it, I think it would show up as generic-password, not internet-password. I think internet password is reserved for websites logins, for example. Just change the above commands to "find-generic-password" and "delete-generic-password"

nevens
New Contributor

This may be of some assistance. https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/security.1.html

After fussing with this a bit, it seems you would want to use the "security find-internet-password" using terminal and whichever flag might be easiest to single this out before using the "security delete-internet-password" command. As I don't know what else might be in the keychain, I wouldn't know if my command would be verbose enough to single it out. Here are a few examples that might work:

security find-internet-password -a ben -s ICE2.ice.local

If this brings up the specific dump you put above, run:

security delete-internet-password -a ben -s ICE2.ice.local

Hopefully there aren't other passwords for "ben" to use on ice2.ice.local, otherwise, I'd have to get a bit more info to zero in on it. It may even be possible to simply use:

security delete-internet-password -s ICE2.ice.local if it's the only account for that server on this machine.

clifhirtle
Contributor II

I posted a scrappy AppleScript I put together last year that goes through and removes and replaces select Keychain items by username. You could likely change the search for username to any other security command variable just as well. We use this in cases where users change their Active Directory usernames external to their Macs, then end up in #KeychainPromptsMeToDeathThenLocksMyAccount situations. Bear with the newbie code and vacant repository. Just setup GitHub for first time ever thanks to encouragement from PSUMacAdmins session:

https://github.com/clifhirtle/keychain

rsh
New Contributor

How about a way to use wildcards with find-generic-password? I want to delete any keychain item associated with my application, but they're all appended with a GUID. So I want to do something like
security find-generic-password -l "com.application.*"

This doesn't work. Does anyone know how I could get this to work?

mm2270
Legendary Contributor II

@rsh][/url][/url][/url][/url Look through the manpage for the security command. There are other flags you can possibly use to zero in on the keychain item.
For example, you might want to use the -s flag for the service type, which may be something like com.application.something, despite the label having the GUID in the name. There are also type (-C) and kind (-D) flags you can use.

I can't say which of these will work for you since I don't know anything about the application and/or the keychain item you're looking to target, so the first thing you should do is list a known keychain item by targeting it by its label name. See what output you get to see what you can use. They're fairly easy to locate. "svce" is the Service string line. "type" is the Type string, etc.

rsh
New Contributor

Thanks for the reply. Here's the keychain information:

$ security find-generic-password -l "com.application.oauth.123456-789"
keychain: "/Users/me/Library/Keychains/login.keychain"
class: "genp"
attributes: 0x00000007 <blob>="com.application.oauth.123456-789" 0x00000008 <blob>=<NULL> "acct"<blob>="file://localhost/Users/me/Documents/file" "cdat"<timedate>=0x32303133313230353134353832325A00 "20131205145822Z�00" "crtr"<uint32>="aapl" "cusi"<sint32>=<NULL> "desc"<blob>=<NULL> "gena"<blob>=<NULL> "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"<timedate>=0x32303133313230353134353832325A00 "20131205145822Z�00" "nega"<sint32>=<NULL> "prot"<blob>=<NULL> "scrp"<sint32>=<NULL> "svce"<blob>="com.application.oauth.123456-789" "type"<uint32>=<NULL>

Service is blob, type is 32-bit unsigned int. But I don't want to simply delete all oauths. I guess I could use -a and match all keychain items with the specific file. But I still run into the problem with wildcards.

mm2270
Legendary Contributor II

That's going to be tricky then since even the service name is using the GUID in it. There's really nothing standard in that output.

You can try doing a full dump of the user keychain and grepping for parts of the keychain name that are known, such as "com.application.oauth" From there you'd need to pull the specific name into a variable to use with another security delete-generic-password command.
For example, something along these lines, (but perhaps with some checks in it):

#!/bin/sh

loggedInUser=$( ls -l /dev/console | awk '{print $3}' )

keychainItem=$( security dump-keychain /Users/$loggedInUser/Library/Keychains/login.keychain | grep 'com.application.oauth' | awk -F'["|"]' '/blob/{print $2}' )

security delete-generic-password /Users/$loggedInUser/Library/Keychains/login.keychain -l "$keychainItem"

Would that work you think? Or is this a case of there are several com.application.oauth.<GUID> keychain entries and you only need to locate one specific one? If so, I'm not sure how you'd possibly do that unless you know the GUID its using up front.

The above is just an example, so PLEASE test anything I wrote above very carefully! This is attempting to delete keychain items. I'm not responsible if it blows away an entire keychains contents since I really didn't test this much at all.

rsh
New Contributor

Haven't fully tested this yet, but it's working good so far. Thanks for your help.

yurypanasyuk
New Contributor III

I know this is an old post but I wanted to ask about a very similar situation. I have a unique service string and label shown below and I would like to remove all found. Preferably by label since I have another profile I would like to remove that does not have a unique service string.

By string - security delete-generic-password -s com.apple.network.eap.user.item.wlan.ssid.DEMO

By label - security delete-generic-password -l DEMO

Here is the output of security dump-keychain /Library/Keychains/system.keychain:

attributes: 0x00000007 <blob>="Wired 802.1X" 0x00000008 <blob>=<NULL> "acct"<blob>=<NULL> "cdat"<timedate>=0x32303135303731333132333830365A00 "20150713123806Z�00" "crtr"<uint32>=<NULL> "cusi"<sint32>=<NULL> "desc"<blob>="802.1X Password" "gena"<blob>=<NULL> "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"<timedate>=0x32303135303731333132333830365A00 "20150713123806Z�00" "nega"<sint32>=<NULL> "prot"<blob>=<NULL> "scrp"<sint32>=<NULL> "svce"<blob>="XXXXXXXXXX" "type"<uint32>=<NULL>

Here is what I copied from the command above and not working right:

loggedInUser=$( ls -l /dev/console | awk '{print $3}' )

keychainItem=$( security dump-keychain /Library/Keychains/system.keychain | grep 'Wired 802.1X' | awk -F'["|"]' '/blob/{print $2}' )

security delete-generic-password /Library/Keychains/system.keychain -l "$keychainItem"

yurypanasyuk
New Contributor III

Never mind got it figured out. Check here for two methods: https://www.jamf.com/jamf-nation/discussions/22246/removing-all-keychains-items-with-unique-label

Chris_Hafner
Valued Contributor II

So, I've listened along here on the post and have a solution to a problem that I would like to run by you folks. Long story short, we use AD to authenticate to a variety of services but our Mac's are unbound and have local accounts (Yes, I'm budgeting for EC... but that is next FY).

We're going to recommend that users change their AD credentials at a certain point. Not a problem right? Here's the fun, we use PaperCut to print from the macs (SMB print queues) and many users will have saved their credentials to the keychain so as to not have to enter their credentials for every print. Once their AD credentials are changed they WILL NOT be asked to update that particular password. So, no more printing until the print is "refreshed" or the keychain entry deleted and recreated.

Does anyone see an issue with or have thoughts about the following simple script (which does function in testing). It's a bit of a heavy club.

#!/bin/sh

#Determine the currently logged in user and save their account name as the loggedInUser
loggedInUser=$( ls -l /dev/console | awk '{print $3}' )

#Find any and all keychain entries of the "network password" kind.
keychainItem=$(security find-internet-password -D "Network Password")

#Delete the specified 'network password' item(s) from the logged in users keychain.
security delete-internet-password /Users/$loggedInUser/Library/Keychains/login.keychain -l "$keychainItem"

exit 0

millersc
Valued Contributor

@Chris_Hafner I'm using a similar script in Self Service for those using our PaperCut systems and have changed their password. Works fine, more about the training aspect.

Chris_Hafner
Valued Contributor II

@millersc Thanks for that. I ended up thinking along the same lines myself and we've decided simply NOT to script this at all. Rather, we've decided to train our users to hit the "Refresh" button on their held print job which conveniently allows them to reset that specific password. This was a major case of me over thinking stuff! Thanks for the advise!

scottd
New Contributor

@Chris_Hafner We have a similar setup (non-bound Macs with Paper-Cut). On our machines, the refresh button does not ask for the new password until we clear if from the keychain. Did you do anything different for that to work for your users? Thanks! Happy to see somebody dealing with the same issues.

Chris_Hafner
Valued Contributor II

Eh... I had a whole write up but then chrome decided that I should submit it. Oh well, in any event, I'll summarize: I've seen this happening more often recently (yet only a handful of times). I'll look a bit deeper into it!

el2493
Contributor II

Hey, trying to figure out how to delete the "Chrome Safe Storage" application password from Keychain (it's giving problems when upgrading Chrome). I tweaked your recommendation and it seems like it should work, but am running into an issue:

#!/bin/sh -v

#Determine the currently logged in user and save their account name as the loggedInUser
loggedInUser=$( ls -l /dev/console | awk '{print $3}' )

#Find any and all keychain entries that contain "Chrome."
keychainItem=$(security find-generic-password -a "Chrome")

#Echo back to make sure it has the right entry
echo $keychainItem

#Delete the specified Chrome' item(s) from the logged in users keychain.
security delete-generic-password /Users/$loggedInUser/Library/Keychains/login.keychain -l "$keychainItem"

exit 0

Everything through echo works as expected, but then when it gets to the delete step it doesn't delete the right entry:

#!/bin/sh -v

loggedInUser=$( ls -l /dev/console | awk '{print $3}' )
 ls -l /dev/console | awk '{print $3}' 

keychainItem=$(security find-generic-password -a "Chrome")
security find-generic-password -a "Chrome"
echo $keychainItem
keychain: "/Users/*******/Library/Keychains/login.keychain-db" version: 512 
class: "genp" attributes: 0x00000007 <blob>="Chrome Safe Storage" 0x00000008 
<blob>=<NULL> "acct"<blob>="Chrome" "cdat"<timedate>=0x32303137303830353136323430345A00 "20170805162404Z" "crtr"<uint32>="aapl" "cusi"<sint32>=<NULL> "desc"<blob>=<NULL> "gena"
<blob>=<NULL> "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"
<timedate>=0x32303137303830353136323430345A00 "20170805162404Z" "nega"
<sint32>=<NULL> "prot"<blob>=<NULL> "scrp"<sint32>=<NULL> "svce"
<blob>="Chrome Safe Storage" "type"<uint32>=<NULL>

security delete-generic-password /Users/$loggedInUser/Library/Keychains/login.keychain -l "$keychainItem"
keychain: "/Users/*******/Library/Keychains/login.keychain-db"
version: 512
class: "genp"
attributes:
    0x00000007 <blob>="Safari Session State Key"
    0x00000008 <blob>=<NULL>
    "acct"<blob>=<NULL>
    "cdat"<timedate>=0x32303137303330323136343234355A00  "20170302164245Z�00"
    "crtr"<uint32>=<NULL>
    "cusi"<sint32>=<NULL>
    "desc"<blob>=<NULL>
    "gena"<blob>=<NULL>
    "icmt"<blob>=<NULL>
    "invi"<sint32>=<NULL>
    "mdat"<timedate>=0x32303137303330323136343234355A00  "20170302164245Z�00"
    "nega"<sint32>=<NULL>
    "prot"<blob>=<NULL>
    "scrp"<sint32>=<NULL>
    "svce"<blob>="Safari Session State Key"
    "type"<uint32>=<NULL>
password has been deleted.

exit 0

So even though echo confirms it's pointing to Chrome Safe Storage, the delete command deletes Safaro Session State Key. Am I missing something obvious? Thanks

mm2270
Legendary Contributor II

@el2493 I see a few things wrong with what you have there. First, you can't use your $keychainItem variable to delete it, because the command you're using to populate that variable returns the entire dump of the keychain password item. Deleting keychain items must use discrete items, like label or service, not the entire item's contents.
Second, you get odd results if the path to the user's keychain is placed before the security flags to do the search. The keychain path should be at the end of the command.

What I would do instead is get the service name by doing a search on Chrome, then use that (the service name) for the deletion. When I looked at my own Chrome Safe Storage item, it's hard to know if the label will work to delete it, but the service name is clear from what I can see.

#!/bin/bash

loggedInUser=$(stat -f%Su /dev/console)

ChromeSafeStorage=$(/usr/bin/security find-generic-password -a "Chrome" /Users/$loggedInUser/Library/Keychains/login.keychain | awk -F'"' '/svce/{print $4}')

if [ "$loggedInUser" != "root" ]; then
    if [ "$ChromeSafeStorage" == "Chrome Safe Storage" ]; then
        echo "Deleting Chrome Safe Storage for user $loggedInUser"
        /usr/bin/security delete-generic-password -s "$ChromeSafeStorage" /Users/$loggedInUser/Library/Keychains/login.keychain
        exit 0
    else
        echo "Could not locate the correct keychain entry to delete"
        exit 0
    fi
else
    echo "No-one logged in. Exiting"
    exit 0
fi

Hope that helps.

el2493
Contributor II

Thanks, that worked perfectly!

el2493
Contributor II

This worked perfectly as a standalone script, tested it on a computer and the keychain entry disappeared.

I made a policy in JSS with the installer as a payload and added this script as a payload. When it runs and it checks the logs I see this:

Script result: #!/bin/sh -v<br/><br/>loggedInUser=$( ls -l /dev/console | awk '{print $3}' )<br/> ls -l /dev/console | awk '{print $3}' <br/><br/>chromeSafeStorage=$(security find-generic-password -a "Chrome" /Users/$loggedInUser/Library/Keychains/login.keychain | awk -F'"' '/svce/{print $4}')<br/>security find-generic-password -a "Chrome" /Users/$loggedInUser/Library/Keychains/login.keychain | awk -F'"' '/svce/{print $4}'<br/>echo $chromeSafeStorage<br/>Chrome Safe Storage<br/><br/>if [ "$loggedInUser" != "root" ]; then<br/> if [ "$chromeSafeStorage" == "Chrome Safe Storage" ]; then<br/> echo "Deleting Chrome Safe Storage for user $loggedInUser"<br/> security delete-generic-password -s "$keychainItem" /Users/$loggedInUser/Library/Keychains/login.keychain<br/> exit 0<br/> else<br/> echo "Could not locate the correct keychain entry to delete"<br/> exit 0<br/> fi<br/>else<br/> echo "No one logged in. Exiting"<br/> exit 0<br/>fi<br/>Deleting Chrome Safe Storage for user *<br/>security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.<br/>

So it again finds the key, confirms that the Svce of the key is "Chrome Safe Storage," but then when it goes to delete it it says it couldn't be found in the keychain (even though if I look in the keychain it's clearly still there). Did I miss something obvious?