Retrieve key from osx keychain - swift

I am trying to retrieve my app's secret key from the keychain such that it can be used to authenticate with the server. I have successfully stored it there but cannot get it back.
func getClientKey(){
let keyValptr:UnsafeMutablePointer<UnsafeMutableRawPointer?>?
let lenPtr:UnsafeMutablePointer<UInt32>? = UInt32(13) //how do i do this?
_ = SecKeychainFindGenericPassword(nil,
UInt32(serviceName.characters.count), serviceName,
UInt32(accountName.characters.count), accountName,
lenPtr, keyValptr, nil)
print(keyValptr)
}
I've commented the line I'm having issues with. How do i obtain a correct pointer to pass into the function? It wants a UnsafeMutablePointer<UInt32>? (where I would choose what the value actually is)

Generally, when you want to pass UnsafeMutablePoiner<T>? (or UnsafeMutablePoiner<T>), you declare a variable of type T (not a pointer to T) and pass it as an inout parameter (prefix &).
So, specific to your issue, your way of passing keyValPtr is also wrong.
For the parameter passwordLength: UnsafeMutablePointer<UInt32>?, you need to declare a variable of type UInt32.
And for passwordData: UnsafeMutablePointer<UnsafeMutableRawPointer?>?, you need to declare a variable of type UnsafeMutableRawPointer?.
And, unfortunately in many cases this may not be a critical issue, you need to calculate length based on UTF-8 representation, when passing Swift String directly to UnsafePointer<Int8>?.
You may need to write something like this:
func getClientKey() {
var keyVal: UnsafeMutableRawPointer? = nil
var len: UInt32 = 13 //<- this value is ignored though...
let status = SecKeychainFindGenericPassword(
nil,
UInt32(serviceName.utf8.count), serviceName, //### Use `utf8.count`
UInt32(accountName.utf8.count), accountName, //### Use `utf8.count`
&len, //### to pass `UnsafeMutablePointer<UInt32>?`, declare a variable of `UInt32`.
&keyVal, //### to pass `UnsafeMutablePointer<UnsafeMutableRawPointer?>?`, declare a variable of `UnsafeMutableRawPointer?`.
nil
)
if status == noErr {
let keyData = Data(bytes: keyVal!, count: Int(len))
//### As noted in the API reference of `SecKeychainFindGenericPassword`,
// "You should use the SecKeychainItemFreeContent function to free the memory pointed to by this parameter."
SecKeychainItemFreeContent(nil, keyVal)
print(keyData as NSData)
print(String(data: keyData, encoding: .utf8) ?? "?")
} else {
//You should not silently ignore erros...
print("Error: \(status)")
}
}

Related

AutoreleasingUnsafeMutablePointer crashes the app

I receive some data from internet and need to guess the encoding if it's not provided, so I use this function stringEncoding(for:encodingOptions:convertedString:usedLossyConversion:), and it requires passing AutoreleasingUnsafeMutablePointer for receiving the converted string, I wrote code like this:
var str = "Hello, playground"
func decode(data: Data) -> String? {
var covertedString = NSString()
let stringPointer = AutoreleasingUnsafeMutablePointer<NSString?>(&covertedString)
guard NSString.stringEncoding(for: data, encodingOptions: nil, convertedString: stringPointer, usedLossyConversion: nil) != 0 else {
return nil
}
return covertedString as String
}
let data = str.data(using: .utf8)!
decode(data: data)
While the covertedString I got out of the function call is correct, the app always crashes. Any idea why AutoreleasingUnsafeMutablePointer is make it crashes? I tried to not passing convertedString, then it's not crashing any more, so looks like it's the root case. Any idea why it's crashing?
I am using Xcode Version 10.1 (10B61), with Swift 4
In your particular case the problem is that you have created an NSString, but then taken a pointer to a NSString?, which is a different thing.
But that doesn't really matter here. You don't create AutoreleasingUnsafeMutablePointer directly (or generally any kind of UnsafePointer). They're not promised to be valid by the time you use them. Instead, you create them implicitly using &.
func decode(data: Data) -> String? {
var convertedString: NSString? = "" // <- Make sure to make this optional
guard NSString.stringEncoding(for: data,
encodingOptions: nil,
convertedString: &convertedString, // <- Use &
usedLossyConversion: nil) != 0
else {
return nil
}
return convertedString as String?
}

How to properly use CFStringGetCString in swift?

I am looking at the docs for
CFStringGetCString
and AXUIElementCopyAttributeValue.
CFStringGetCString takes the param buffer: UnsafeMutablePointer<Int8>!
AXUIElementCopyAttributeValue takes the param value: UnsafeMutablePointer<CFTypeRef?>
For the latter, I can do a call like this:
var value: CFTypeRef?
let err = AXUIElementCopyAttributeValue(element, attribute as CFString, &value);
This satisfies the doc asking for an UnsafeMutablePointer of type CFTypeRef.
However I can't get the same logic to apply by doing
let buffer: Int8!
CFStringGetCString(attribute as! CFString, &buffer, 2048, CFStringBuiltInEncodings.UTF8.rawValue)
I also tried
let buffer: Int8?
CFStringGetCString(attribute as! CFString, &buffer!, 2048, CFStringBuiltInEncodings.UTF8.rawValue)
Either way, it complains about using buffer before it's initialized, even though it never complained about value in the working method with similar param requirements.
All the working examples I've seen for CFStringGetCString are using objective-c like syntax with *. Not sure what the proper swift way is here.
I also tried this way to get the value I wanted:
let app = AXUIElementCreateSystemWide();
var valueString = "";
var value: CFTypeRef?
// An exception on execution happens here when passing app
// Passing in the element I clicked instead of app
// yields error -25205 (attributeunsupported)
let err = AXUIElementCopyAttributeValue(app, "AXFocusedApplication" as CFString, &value);
if (err == AXError.success) {
valueString = value! as! NSString as String;
} else {
print("ERROR!");
print(err.rawValue);
}
return valueString;
Why are you torturing yourself with CFStringGetCString? If you have a CFString in Swift, you can cast it to a String and get a C string from that:
let cString: [Int8] = (cfString as String).cString(using: .utf8)!
Note also that the value of the kAXFocusedApplicationAttribute is not a CFString. It is an AXUIElement.
Here's my playground test:
import Foundation
import CoreFoundation
let axSystem = AXUIElementCreateSystemWide()
var cfValue: CFTypeRef?
AXUIElementCopyAttributeValue(axSystem, kAXFocusedApplicationAttribute as CFString, &cfValue)
if let cfValue = cfValue, CFGetTypeID(cfValue) == AXUIElementGetTypeID() {
let axFocusedApplication = cfValue
print(axFocusedApplication)
}
The first time I executed this playground, I got a system dialog box telling me that I need to give Xcode permission to control my computer. I went to System Preferences > Security & Privacy > Privacy > Accessibility, found Xcode at the bottom of the list, and turned on its checkbox.
Here's the output of the playground:
<AXUIElement Application 0x7fb2d60001c0> {pid=30253}
I assume you're on macOS since the AXUI API is only available on macOS. If you just want the name of the front application as a string, you can do this:
if let frontAppName = NSWorkspace.shared.frontmostApplication?.localizedName {
print(frontAppName)
}

how to unwrap optionals, how can i write this code to not have any ? or ! in it, or is it possible?

I am having a hard time to rewrite this code so that there are no optionals ? in it or force unwrapping ! So far I was able to get it to work but with the optional in the output. I would like the output to not have the optional in it.
class CeaserCipher {
var secret: Int? = 0
func setSecret(_ maybeString: String?) {
guard let stringSecret = maybeString else {
return
}
self.secret = Int(stringSecret)
}
}
let cipher = CeaserCipher()
cipher.setSecret(nil)
print(cipher.secret)
cipher.setSecret("ten")
print(cipher.secret)
cipher.setSecret("125")
print(cipher.secret)
So, you have a cat, there are many ways you might skin it.
You "could" make the cipher immutable by providing a failable constructor, for example...
struct CeaserCipher {
let secret: Int
init?(string: String) {
guard let value = Int(string) else { return nil }
secret = value
}
}
This doesn't stop you needing to deal with optionals, but it means that an instance of CeaserCipher will be valid.
The struct is focrcing at least one requirement, that you have a non-optional String, so you will need to valid that first
So if you did something like...
let cipher = CeaserCipher(string: "Bad")
cipher would be nil and you'd need to deal with it, but if you did something like...
let cipher = CeaserCipher(string: "123456789")
cipher would be a valid instance and you could work with it.
Using guard and if let are important here, as they will allow you to avoid crashing the code, which you would use would depend on your needs.
guard let cipher = CeaserCipher(string: "123456789") else {
// Cipher is invalid, deal with it...
return
}
// Valid cipher, continue to work with it
or
if let cipher = CeaserCipher(string: "123456789") {
// Valid cipher, continue to work with it
} else {
// Cipher is invalid, deal with it...or not
}
The point of the example is, you will either get a valid instance of CeaserCipher or a nil, which is "generally" safer then having an instance which is in a invalid state and generally easier to deal with

Swift 4 - Catch Error if Value not in Plist

I have this code
let path = self.userDesktopDirectory + "/Library/Preferences/.GlobalPreferences.plist"
let dictRoot = NSDictionary(contentsOfFile: path)
if let dict = dictRoot{
try print(dict["AppleLocale"] as! String)
}
If the Value "AppleLocale" didnt exists the script crashes. What I must add to "catch" the Error and avoid the crash?
If the Value "AppleLocale" didnt exists the script crashes. What I
must add to "catch" the Error and avoid the crash?
depends on what's the reason for causing the crash. Mentioning that "If the Value AppleLocale didnt exists" means the the reason for the crash would be the force casting:
dict["AppleLocale"] as! String
probably, it has nothing to do with the try, it would be:
Unexpectedly found nil while unwrapping an Optional value
Means that at some point dict["AppleLocale"] could be nil or even if it contains a value as not a string it will crash (optional). You have to make sure that dict["AppleLocale"] is a valid (not nil) string, there are more than just one approach to follow for doing it, for instance you could do optional binding, like this:
let path = self.userDesktopDirectory + "/Library/Preferences/.GlobalPreferences.plist"
let dictRoot = NSDictionary(contentsOfFile: path)
if let dict = dictRoot{
if let appleLocale = dict["AppleLocale"] as? String {
print(appleLocale)
} else {
// `dict["AppleLocale"]` is nil OR contains not string value
}
}
Actually, I would assume that you don't have to deal with try for such a case.

Making a variable from if statement global

While encoding JSON, I´m unwrapping stuff with an if let statement, but I'd like to make a variable globally available
do {
if
let json = try JSONSerialization.jsonObject(with: data) as? [String: String],
let jsonIsExistant = json["isExistant"]
{
// Here I would like to make jsonIsExistant globally available
}
Is this even possible? If it isn't, I could make an if statement inside of this one, but I don't think that would be clever or even possible.
delclare jsonIsExistant at the place you want it. If you are making an iOS App, than above viewDidLoad() create the variable
var jsonIsExistant: String?
then at this point use it
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String],
let tempJsonIsExistant = json["isExistant"] {
jsonIsExistant = tempJsonIsExistant
}
}
This could be rewritten like so though
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] {
jsonIsExistant = json["isExistant"]
}
} catch {
//handle error
}
If handled the second way, then you have to check if jsonIsExistant is nil before use, or you could unwrap it immediately with a ! if you are sure it will always have a field "isExistant" every time that it succeeds at becoming json.
It doesn't make sense to expose a variable to the outside of an if let statement:
if let json = ... {
//This code will only run if json is non-nil.
//That means json is guaranteed to be non-nil here.
}
//This code will run whether or not json is nil.
//There is not a guarantee json is non-nil.
You have a few other options, depending on what you want to do:
You can put the rest of the code that needs json inside of the if. You said you didn't know if nested if statements are "clever or even possible." They're possible, and programmers use them quite often. You also could extract it into another function:
func doStuff(json: String) {
//do stuff with json
}
//...
if let json = ... {
doStuff(json: json)
}
If you know that JSON shouldn't ever be nil, you can force-unwrap it with !:
let json = ...!
You can make the variable global using a guard statement. The code inside of the guard will only run if json is nil. The body of a guard statement must exit the enclosing scope, for example by throwing an error, by returning from the function, or with a labeled break:
//throw an error
do {
guard let json = ... else {
throw SomeError
}
//do stuff with json -- it's guaranteed to be non-nil here.
}
//return from the function
guard let json = ... else {
return
}
//do stuff with json -- it's guaranteed to be non-nil here.
//labeled break
doStuff: do {
guard let json = ... else {
break doStuff
}
//do stuff with json -- it's guaranteed to be non-nil here.
}