Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

gpchess2k

macrumors member
Original poster
Oct 12, 2015
42
0
Hello Everyone!

Looking for a little guidance on removing all instances of a generic password keychain by either the service (svce) or label string. I can do it once at a time but I sometimes have machines that have 15+. Here is how I am able to one at a time:

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

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


And attempting to all at once using the awk command:

security find-generic-password -s "com.apple.network.eap.user.item.wlan.ssid.DEMO" | \ sudo awk ’/svce/{system(“security delete-generic-password -s “com.apple.network.eap.user.item.wlan.ssid.DEMO)}’


That last one has some bad syntax but cant figure it out =(
 
As a general rule, when you get errors, please post the complete actual error message.


Without seeing your error message, my first guess is there's a quoting problem.

Your last example contains curly (smart) quotes instead of straight (neutral, plain, dumb) quotes.

The shell, which is the command interpreter in a Terminal window, only works with straight quotes. It doesn't work with curly quotes.

My guess is that you copied to the clipboard from some location that's using curly/smart quotes, then pasted it into a Terminal window (or drag-n-dropped it). If you copied it from a web page, please post its URL, so we can see the original.

Here's your original, in a large text size:

security find-generic-password -s "com.apple.network.eap.user.item.wlan.ssid.DEMO" | \ sudo awk ’/svce/{system(“security delete-generic-password -s “com.apple.network.eap.user.item.wlan.ssid.DEMO)}’

Notice the single-quote before /svce/ is curly or slanted, as is the single-quote after DEMO)}. Compare how the quotes appear above with the example shown below.

The double-quote in the middle of system(“security is also curly or slanted, as is the double-quote before com.apple. The first double-quotes (before the | symbol) are fine, as they're straight quotes.

The placement of the last double-quote also seems unusual. If you expect to run the command, then the whole command string needs to be in double quotes. The quotes also need to be straight.

Here's an example with straight quotes, with the closing double-quote moved to what seems like a saner location:

security find-generic-password -s "com.apple.network.eap.user.item.wlan.ssid.DEMO" | \ sudo awk '/svce/{system("security delete-generic-password -s com.apple.network.eap.user.item.wlan.ssid.DEMO")}'

I can't vouch for the correctness of the awk script itself. I'm only pointing out the obvious quoting errors (not straight), and what seems to be a misplaced closing double-quote.
 
Thanks chown! That got rid of my errors and command executes but still only deleting one entry instead of all with the same string. Current command:

security find-generic-password -s "test" | \sudo awk '/svce/{system("security delete-generic-password -s test")}'
 
Thanks chown! That got rid of my errors and command executes but still only deleting one entry instead of all with the same string. Current command:

security find-generic-password -s "test" | \sudo awk '/svce/{system("security delete-generic-password -s test")}'
OK, let's break things down, and look at details.

First, post the output of this command:
Code:
security find-generic-password -s "test" | grep 'svce'
If there are multiple lines, then the awk program would be expected to run for each line. Conversely, if there's only one line, then the awk program would be expected to only run once.

What are you expecting as output? Please describe the rationale for this expectation.

My guess is there will be a single line, but it's just a guess.


Second, how did you decide this was the awk command you should run to delete multiple items?
Is it something you developed yourself? If so, based on what? Reading the awk man page?

Did you copy it verbatim from somewhere? If so, exactly where?

Or maybe you copied and modified it from somewhere. Again, exactly where?

This is only your second thread on MacRumors, so I have no way of knowing how much skill or experience you have. Your other thread didn't provide much additional info about you. All we know is what you tell us. Details and context are important.


Finally, if everything is on a single command line, you don't need the '\' before 'sudo'. You can get into trouble with extraneous backslashes, or missing spaces, so it would be a good idea to tell us how you decided to put that backslash in there.
 
security find-generic-password -s "test" | grep 'svce' outputs a single line when there should be two: "svce"<blob>="test".

The example of the AWK command I found was this:

security find-certificate -c "certificatename" -a -Z | \

sudo awk '/SHA-1/{system("security delete-certificate -Z "$NF)}'



I found a better example of what I am trying to do but cant figure out the print flags reading the manual for awk: Best to remove keychains by label instead by service tag.

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"
 
security find-generic-password -s "test" | grep 'svce' outputs a single line when there should be two: "svce"<blob>="test".

The example of the AWK command I found was this:

security find-certificate -c "certificatename" -a -Z | \

sudo awk '/SHA-1/{system("security delete-certificate -Z "$NF)}'
1. Please use CODE tags.
The only reason I used large type was to make it easier to visually identify the nature of the quote.

2. Where did you find this example awk command? Please be specific. What is the URL?
This command deletes multiple certificates only because the find-certificate sub-command has the -a option, which lists all certificates. There is no similar option I can see for the find-generic-password or delete-generic-password sub-commands. Therefore, trying to apply this command line to other than delete-certificate can't possibly work.

The use of 'sudo' is only because this command-line can delete certificates in the system-wide keychains. Deleting items in only the user keychain doesn't need 'sudo', and it would be unwise to use it because it requires an admin password.


I found a better example of what I am trying to do but cant figure out the print flags reading the manual for awk: Best to remove keychains by label instead by service tag.

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"

3. Where did you find this example? Please be specific. What is the URL?
If the output collected into keychainItem contains multiple blobs, then keychainItem will be multiple strings. That seems unlikely to work when passed as the argument of the -l option.

That's also a strange way to refer to the current user's home directory. Either $HOME or ~/ would be simpler. This makes me wonder about the quality of the example.


If the problem to be solved is the deletion of all keychain items with the label DEMO, those items being located only in the user keychain, then it seems unlikely to me that 'awk' will readily help accomplish this.

Please explain how you decided that 'awk' was the most suitable tool for this task. Again, this goes to helping us understand what base of experience you're approaching this from.


The way I'd probably approach this is with a loop construct in bash, i.e. a shell script. The loop body might try to delete the desired item, and if that deletion failed (status code $? non-zero), then break the loop. That's just a conceptual outline, not a detailed plan.

If you want to try solving this with a shell loop, then please state that. If you do, then I'll be asking you to post some output produced by the 'security' command, which may reveal something you'd prefer be kept secret. I know of no other way to approach this, because I don't have a keychain with a bunch of deletable generic passwords handy to test on.
 
Last edited:
Herers my source: https://www.jamf.com/jamf-nation/discussions/7530/delete-individual-keychain-item

I dont care how its done but this small command will be part of a script I have already built with AppleScript. I can run the bash shell script from within so should be ok. I was thinking maybe Applescript will work even. Since running that single command works fine maybe theres a way to loop it until error and then stop? But like I said whatever is easiest. Ill have some time in the next few days to really study up and test.
 
Herers my source: https://www.jamf.com/jamf-nation/discussions/7530/delete-individual-keychain-item

I dont care how its done but this small command will be part of a script I have already built with AppleScript. I can run the bash shell script from within so should be ok. I was thinking maybe Applescript will work even. Since running that single command works fine maybe theres a way to loop it until error and then stop? But like I said whatever is easiest. Ill have some time in the next few days to really study up and test.
Thanks for posting the origin, it helps explain a lot.

In order to solve this, I need to get a better understanding of exactly how a generic password will be represented in the output of 'security'.

Please post the output of this command:
Code:
security find-generic-password -l DEMO ; echo "status: $?"

Copy and paste the complete actual output, inside CODE tags. If the output is an error message, then post the error message.

The above command might output something secret, so be sure you're willing to accept this risk. For example, if the password is something you're using only for this service, then losing its secrecy is not important, because you can make another password. On the other hand, if you reuse the same password for other purposes, then losing its secrecy is important.

EDIT: I just double-checked, and the command-line given above will NOT output any secrets. Thus, I've put a strike-through on my prior precaution.


Next, post the output of this command, again within CODE tags:
Code:
security dump-keychain | grep DEMO | wc
The output of this command will be a single line with numbers. It won't have any secrets.
 
Last edited:
Wow thats where the CODE tags button was! lol Thanks!
Here is the first output with only one entry when I have 3:

Code:
version: 512 class: "genp" attributes: 0x00000007 <blob>="DEMO" 0x00000008 <blob>=<NULL> "acct"<blob>="DEMO" "cdat"<timedate>=0x32303136313132333233353134375A00 "20161123235147Z\000" "crtr"<uint32>=<NULL> "cusi"<sint32>=<NULL> "desc"<blob>=<NULL> "gena"<blob>=<NULL> "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"<timedate>=0x32303136313132333233353134375A00 "20161123235147Z\000" "nega"<sint32>=<NULL> "prot"<blob>=<NULL> "scrp"<sint32>=<NULL> "svce"<blob>="DEMO" "type"<uint32>=<NULL> status: 0

Here is the second:
Code:
       9      12     233
 
Here is the first output with only one entry when I have 3:

Code:
version: 512 class: "genp" attributes: 0x00000007 <blob>="DEMO" 0x00000008 <blob>=<NULL> "acct"<blob>="DEMO" "cdat"<timedate>=0x32303136313132333233353134375A00 "20161123235147Z\000" "crtr"<uint32>=<NULL> "cusi"<sint32>=<NULL> "desc"<blob>=<NULL> "gena"<blob>=<NULL> "icmt"<blob>=<NULL> "invi"<sint32>=<NULL> "mdat"<timedate>=0x32303136313132333233353134375A00 "20161123235147Z\000" "nega"<sint32>=<NULL> "prot"<blob>=<NULL> "scrp"<sint32>=<NULL> "svce"<blob>="DEMO" "type"<uint32>=<NULL> status: 0
Was the output really all on a single line like that?

There should be some line breaks (newlines) in there. At the very least, there should be a newline before the "status: 0".


Exactly what OS version are you running on?


Please post the output of this command, using CODE tags:
Code:
security dump-keychain | grep DEMO
There should be 9 lines of output. We know this because 9 is the first number from the 2nd command's output you previously posted.

There won't be any secrets in this output.

The output should look something like this:
Code:
    0x00000007 <blob>="service.1.DEMO"
    "svce"<blob>="service.1.DEMO"
    0x00000007 <blob>="service.2.DEMO"
    "svce"<blob>="service.2.DEMO"
That's from test data on my machine; yours will have other lines.
 
Sorry mistake. Running on Sierra. Here is the original output:

Code:
version: 512
class: "genp"
attributes:
    0x00000007 <blob>="DEMO"
    0x00000008 <blob>=<NULL>
    "acct"<blob>="DEMO"
    "cdat"<timedate>=0x32303136313132333233353134375A00  "20161123235147Z\000"
    "crtr"<uint32>=<NULL>
    "cusi"<sint32>=<NULL>
    "desc"<blob>=<NULL>
    "gena"<blob>=<NULL>
    "icmt"<blob>=<NULL>
    "invi"<sint32>=<NULL>
    "mdat"<timedate>=0x32303136313132333233353134375A00  "20161123235147Z\000"
    "nega"<sint32>=<NULL>
    "prot"<blob>=<NULL>
    "scrp"<sint32>=<NULL>
    "svce"<blob>="DEMO"
    "type"<uint32>=<NULL>
status: 0


New output of grep DEMO:

Code:
    0x00000007 <blob>="DEMO"
    "acct"<blob>="DEMO"
    "svce"<blob>="DEMO"
    0x00000007 <blob>="DEMO"
    "acct"<blob>="DEMO1"
    "svce"<blob>="DEMO"
    0x00000007 <blob>="DEMO"
    "acct"<blob>="DEMO2"
    "svce"<blob>="DEMO"
 
Here's a shell command sequence that deletes all generic passwords whose name (label) is "DEMO":
Code:
while security delete-generic-password  -l 'DEMO' >/dev/null
do true; done

This works by trying to delete an item whose name (label) is DEMO. The output is redirected to /dev/null (the bit bucket), otherwise you'll get a dump of the item being deleted (at least it does that here).

If an item named DEMO was deleted, then the loop repeats.
If an item named DEMO wasn't deleted, then the loop halts (breaks).

Thus, the loop continues to delete keychain items until no item named DEMO can be deleted.


Only the user keychain will be affected.
If you need to delete from other keychains, ask for that.


Any item that isn't a generic password should be unaffected, even if its name is DEMO.

Only items whose complete name is DEMO will be affected.
The name is NOT case-sensitive. That is, "Demo", "DEMO", and "demo" will all be deleted.

Names that contain the word DEMO, e.g. "DEMOLISH", should not be affected.


There are other ways of doing this. This is just one way.
 
  • Like
Reactions: gpchess2k
Amazing yes! That works so perfectly. Chown i really appreciate it. Thanks for your patience as well!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.