SecretStoreNovell Single Sign-onVersion 1.1
Articles and Tips: article
Network Security Development Product Group
01 Apr 2000
As a foundation to the upcoming version 2.0 in the Spring of 2000, a set of enhancements has been added to the existing Novell Single Sign-on version 1.0. Some of these enhancements pave the way for migration to the future version. Other important enhancements deal with performance in the way the client goes about locating the service on the network. Version 1.1 has a localized companion that will be released worldwide for international customers. All of the Novell connectors have been updated for the new release with enhancements. Last but not least, the security enhancements provide better protection and confidentiality for the clients of the service.
In this article the updates in all of the three categories mentioned above will be discussed in detail. In addition to the updates, the rationale behind the new APIs will be discussed with some examples that match the postings of Novell's NDK.
- Security Enhancements
- Performance Enhancements
- New Features
- New Console1 Snapin
- Original APIs Support
- Localization of the Install and Connectors
- Sample Code for 1.1 NSSO
Security Enhancements
Novell Single Sign-on is built on Novell's International Cryptographic Services (NICI). NICI provides the means for applications independence from having different builds for different cryptographic strengths for export and domestic purposes. In version 1.0, NSSO client had the export version of the NICI statically linked into it. This was due to the client NICI being in its preliminary stages and not available as an external service on the client operating system platform. As a result, in order to be able to get worldwide export classification for the product, it had to be built and packaged with the lowest common denominator for cryptography. With respect to the strength of the cryptography, this meant that the negotiation between NSSO client and the SecretStore would result in a 56 bit strength session key.
NSSO client cryptographic operations can be summarized in negotiating the strongest common cryptographic algorithm between the client and the server for encrypting the data on the wire. A session key, negotiated between the NICI client and server, is used to encrypt the key to the NSSO common cryptographic algorithm for protection. Both the session key and the algorithm are known to NICI on the server and client and are negotiated at the end of the successful Novell client authentication process. NSSO has always been able to select the strongest cryptographic algorithm for the wire encryption, regardless of the underlying cryptographic service. As mentioned before, this is the feature of the applications built on top of the NICI. The grade of the cryptographic service for the session was the effect of the session keys being export grade. The export grade of the cryptographic service on the wire has nothing to do with the grade of the cryptographic strength of the SecretStore. SecretStore selects the strongest algorithm available through the server NICI for encrypting secrets for the purpose of storage. In version 1.0 NSSO, it was possible to have export grade cryptographic services on the wire and domestic grade cryptographic services in the SecretStore resulting from the server being in the United States or Canada and having had the domestic strength NICI shipped with it.
In version 1.1 or greater, NSSO client does not statically link the NICI into it. The proper strength client NICI for the locale can be downloaded from http://www.novell.com/products/cryptography free of charge and should be installed separately on the client before NSSO client can be operational. The version for this NICI is 1.5x. Consequently, newer NSSO clients can benefit from stronger cryptography based on their locale.
Performance Enhancements
Version 1.0 NSSO client was designed to go query the root of the NDS partition to obtain a list of the writable replicas in that partition. Then, these writable replicas were each pinged by the NSSO client until one that had the SecretStore NLM and the service installed on it responded. After this stage, the access to the SecretStore was established and operation could continue. This mode of operations posed a problem for the networks that had their roots over WAN links. This required having a replica of the root locally and a copy of the writable replicas on the root in the large distributed networks, for optimal performance.
The solution to this problem has been implemented in the NSSO client versions 1.1 or better. Newer client will first ping the primary connection for SecretStore. This is the connection to the server that holds the writable copy of the user's object unless the use has changed connection to a different tree or server since logging in. If the connection has not changed since logging in and the SecretStore is installed on that server, the access will be established to the services. In case of failure due to a change of the primary server since logging in or no SecretStore on the target server, the client will revert back to the old scheme as described above to locate the service. Proper design of the NDS by IS personnel is easier and cheaper and performance too can be improved more easily.
New Features
There is a new API (NSSOGetServiceInfo) that allows the NSSO client to return information regarding the service. The server related parameters are optional and using them results in a ping to the SecretStore for obtaining the information.
The following code sample demonstrates the use of the new NSSOGetServiceInfo call.
if(rcode = NSSOGetServiceInfo(&cVer, &sVer, &cCrypto, &sCrypto, NULL))& { printf("\nError [%d] NSSOGetServiceInfo\n", rcode); } else { printf("\nClient Version = [%d.%x]\n", (cVer >> 8), (cVer & 0x000000FF));& 0x000000FF)); printf("Server Version = [%d.%x]\n\n", (sVer >> 8), (sVer & 0x000000FF));& 0x000000FF)); if(cCrypto == NSSO_NICI_DOMESTIC_ENGINE) { printf("Client Crypto Strength = DOMESTIC\n"); } else if(cCrypto == NSSO_NICI_EXPORT_ENGINE) { printf("Client Crypto Strength = EXPORT\n"); }
if(sCrypto == NSSO_NICI_DOMESTIC_ENGINE) { printf("Server Crypto Strength = DOMESTIC\n"); } else if(sCrypto == NSSO_NICI_EXPORT_ENGINE) { printf("Server Crypto Strength = EXPORT\n"); } }
NSSO APIs on the different versions of the Microsoft Windows operating system used the _cdecl parameter passing convention on the stack. This made it difficult for developers who needed to write Visual Basic and COM (Component Object Model) wrappers on top of the NSSO APIs. New APIs (version 1.1 and greater) use _stdcall parameter passing convention that solves that problem for the developers and allows them to write necessary wrappers.
The future release of the NDK will provide a set of VB, COM, and Java wrappers for the developers. These new wrappers are based on the new APIs and support the new features.
There is a new lock removing feature built into the NSSOUnlockSecrets that allows the locked secrets to be removed from the SecretStore when the NDS password change is due to forgotten password problem. This can be accomplished by setting the NSSO_REMOVE_LOCK_FROM_STORE_F on this call.
In order to provide a simple way for users to detect a lock on the SecretStore and unlock it, this feature has been implemented in the Novell's Client32 for Windows NT/2000 in versions 4.7 or better. As a result, a locked SecretStore is detected at the point of logging on to the workstation, and the user can choose to unlock or remove the lock from the workstation.
Code samples A and B show the difference between removing the lock from SecretStore by removing all of the locked secrets and unlocking the SecretStore using the short form of NSSOUnlockSecrets:
Code Sample A:
// remove lock from the SecretStore if (rcode = NSSO_UnlockSecrets(NSSO_REMOVE_LOCK_FROM_STORE_F, NULL)) { printf("Error [%d] NSSOUnlockSecrets (remove locked secrets) \n", rcode); } else { printf("Secret Store Lock Removed...\n"); }
Code Sample B:
// unlock the SecretStore if (rcode = NSSO_UnlockSecrets(0, pword)) { printf("Error [%d] NSSOUnlockSecrets (unlocked secrerts)\n", rcode); } else { printf("Secret Store Unlocked...\n"); }
NSSO version 1.0 required that all strings be passed in their local code page and internally converted them to Unicode for internal consumption. This caused difficulties for some products that already had strings in Unicode. They had to convert them into local code page before passing them to NSSO APIs to be internally converted to Unicode again. NSSO version 1.1 and greater is capable of recognizing the Unicode strings using NSSO_ALL_STRINGS_UNICODE_F flag. Passed in on the APIs, this flag causes the system to bypass the conversions and return all results in Unicode to the caller. This is a universal flag for all SecretStore calls.
The following code sample demonstrates the use of this new feature with NSSOEnumerateSecretIDs:
// enumerate the secrets count = 0; uniSecIDList.len = secretIDBuf->len = NSSO_ENUM_BUFFER_GUESS; secretIDBuf->data = secBuf; if (rcode = NWLocalToUnicode(uniHandle, (unsigned short *)uniSrchStr.id, sizeof(uniSrchStr.id), "*", (unicode) NULL, (nuint *)&uniSrchStr.len))& { printf("Error [%d] NWLocalToUnicode Failed\n", rcode); Pause(); } if (rcode = NSSO_EnumerateSecretIDs(NSSO_ALL_STRINGS_UNICODE_F, uniSrchStr.id, &count, &uniSecIDList))& { printf("Error [%d] NSSOEnumerateSecretIDs\n", rcode); } else { // convert the list back from unicode to print if(rcode = NWUnicodeToLocal(uniHandle, secretIDBuf->data, secretIDBuf->len, (punicode)uniSecIDList.data, (nuint8)NULL, (pnuint)&secretIDBuf->len))&
{ printf("Error [%d] NWUnicodeToLocal Failed\n", rcode); } else { printf("Number of Secrets = [%d]\nRaw Secret ID Buffer from SS [%s]\n", count, (char*)secretIDBuf->data); } nameStr = strtok((char *)&secretIDBuf->data[0], "*");& for(i = 0; i < count; i++) { strcpy(secretID[i].id, nameStr); secretID[i].len = strlen(secretID[i].id)+1; printf("Extracted SecretID[%d] = [%s], len = [%d]\n", i, secretID[i].id, secretID[i].len); nameStr = strtok(NULL, "*"); } }
New Console1 Snapin
There is a new Console1 snapin that supports the regular expression search features of the SecretStore when enumerating the secrets as well as ability to remove locks from a locked SecretStore. A notable improvement on the new snapin, and Console1 itself, is the performance. The new snapin is written to operate on Console1 version 1.2b.20 or newer.
Original APIs Support
NSSO DLL on the client still exports the original version 1.0 APIs. These APIs are implemented as wrappers on top of the new APIs. Since new APIs are designed to be future compatible with complete support for the upcoming new features, they should be used for new connector implementations. Original APIs that are exported form the NSSO version 1.1. DLL are not capable of supporting and passing all of the new features to the new APIs, and they are only supported for backward compatibility. The support for these APIs will be discontinued in a future version. For now, they are there to allow for the existing Novell and customer connectors to continue operations.
Localization of the Install and Connectors
Installation and all of the new versions of connectors (Notes, Entrust, etc.) that are associated with NSSO version 1.1 are localized and language enabled for export out of United States and Canada.
Sample Code for 1.1 NSSO
The following sample code is a working code that demonstrates the use of all of the NSSO version 1.1 long form of the APIs in a situation where the client DLL has been loaded directly by the sample code. Microsoft Visual C++ version 6.0 has been used to compile this code.
#include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <nwnet.h> #include <nwdsapi.h> #include <nwndscon.h> #include <nwcalls.h> #include <nwclxcon.h> #include <nwlocale.h> #include <unicode.h> #include <string.h> #include <nwdsdc.h> #include "nwss.h" /****************************************************************************** *** This code is available at "www.developer.novell.com/ndk/ *** sample code for the old wrapper APIs for version 1.1 and above. *** demonstrating the loading of the DLL without the lib and using Unicode. ******************************************************************************/ #define PASSWORD "kIllERaPp11tWO99" / set types and initialize for the new APIs to bypass loading the DLL typedef NWRCODE (__stdcall *NSSOADDSECRETID_T) (SS_CONTEXT_T *, char *, unsigned long, SS_SECRET_ID_T *, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOWRITESECRET_T) (SS_CONTEXT_T *, char *, unsigned long, SS_SECRET_ID_T *, SS_SECRET_T *, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOREADSECRET_T) (SS_CONTEXT_T *, char *, unsigned long, SS_SECRET_ID_T *, SS_SECRET_T *, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOREMOVESECRETID_T) (SS_CONTEXT_T *, char *, unsigned long, SS_SECRET_ID_T *, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOREMOVESECRETSTORE_T) (SS_CONTEXT_T *, char *, unsigned long, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOENUMERATESECRETIDS_T) (SS_CONTEXT_T *, char *, unsigned long, char *, unsigned long *, SS_SECRET_T *, SS_EXT_T *);
typedef NWRCODE (__stdcall *NSSOUNLOCKSECRETS_T) (SS_CONTEXT_T *, char *, unsigned long, char *, SS_EXT_T *); typedef NWRCODE (__stdcall *NSSOGETSERVICEINFO_T) (unsigned long *, unsigned long *, unsigned long *, unsigned long *, SS_EXT_T *); // set types and initialize for the original APIs to bypass loading the DLL typedef NWRCODE (_cdecl *NWSSADDSECRETID_T) (NWDSContextHandle, char *, long, SS_SECRET_ID_T *, void *); typedef NWRCODE (_cdecl *NWSSWRITESECRET_T) (NWDSContextHandle, char *, long, SS_SECRET_ID_T *, SS_SECRET_T *, void *); typedef NWRCODE (_cdecl *NWSSREADSECRET_T) (NWDSContextHandle, char *, long, SS_SECRET_ID_T *, SS_SECRET_T *, SS_EXTINFO_T *); typedef NWRCODE (_cdecl *NWSSREMOVESECRETID_T) (NWDSContextHandle, char *, long, SS_SECRET_ID_T *, void *); typedef NWRCODE (_cdecl *NWSSREMOVESECRETSTORE_T) (NWDSContextHandle, char *, long, void *); typedef NWRCODE (_cdecl *NWSSENUMERATESECRETIDS_T) (NWDSContextHandle, char *, long, char *, unsigned long *, SS_SECRET_T *, void *); typedef NWRCODE (_cdecl *NWSSUNLOCKSECRETS_T) (NWDSContextHandle, char *, long, char *, void *); // new _stdcall APIs static NSSOADDSECRETID_T p_NSSOAddSecretID = NULL; static NSSOWRITESECRET_T p_NSSOWriteSecret = NULL; static NSSOREADSECRET_T p_NSSOReadSecret = NULL; static NSSOREMOVESECRETID_T p_NSSORemoveSecretID = NULL; static NSSOREMOVESECRETSTORE_T p_NSSORemoveSecretStore = NULL; static NSSOENUMERATESECRETIDS_T p_NSSOEnumerateSecretIDs = NULL; static NSSOUNLOCKSECRETS_T p_NSSOUnlockSecrets = NULL; static NSSOGETSERVICEINFO_T p_NSSOGetServiceInfo = NULL; // original _cdecl APIs static NWSSADDSECRETID_T p_NWSSAddSecretID = NULL; static NWSSWRITESECRET_T p_NWSSWriteSecret = NULL; static NWSSREADSECRET_T p_NWSSReadSecret = NULL; static NWSSREMOVESECRETID_T p_NWSSRemoveSecretID = NULL; static NWSSREMOVESECRETSTORE_T p_NWSSRemoveSecretStore = NULL; static NWSSENUMERATESECRETIDS_T p_NWSSEnumerateSecretIDs = NULL; static NWSSUNLOCKSECRETS_T p_NWSSUnlockSecrets = NULL; NWDSContextHandle context = -1; char objDN[MAX_DN_CHARS]; nptr uniHandle; //* global for local to unicode conversions nptr uniHandle; //* global for unicode to local conversions /* * NAME - InitNDS * * DESCRIPTION * This function initializes the NDS related resources. * */ static int InitNDS(void)
{ uint32 reqFlagValue; LCONV convert; NWDSCreateContextHandle(&context);& memset(objDN, 0, MAX_DN_CHARS); //* Initialize NWCalls and unicode tables NWLlocaleconv(&convert); & NWInitUnicodeTables(convert.country_id, convert.code_page); NWGetUnicodeToLocalHandle(&uniHandle);& NWGetLocalToUnicodeHandle(&uniHandle);& if(NWDSGetContext(context, DCK_FLAGS, &reqFlagValue ))& { return(NSSO_E_NDS_INTERNAL_FAILURE); } reqFlagValue |= DCV_TYPELESS_NAMES | DCV_XLATE_STRINGS; if(NWDSSetContext(context, DCK_FLAGS, &reqFlagValue ))& { return(NSSO_E_NDS_INTERNAL_FAILURE); } if(NWDSSetContext(context, DCK_NAME_CONTEXT, DS_ROOT_NAME )) { return(NSSO_E_NDS_INTERNAL_FAILURE); } if (NWDSWhoAmI(context, objDN)) { return(NSSO_E_NDS_INTERNAL_FAILURE); } return(NSSO_SUCCESS); } /* * NAME - DeInitNDS * * DESCRIPTION * This function frees the NDS related resources. * */ static void DeInitNDS(void) { NWDSFreeContext( context ); NWFreeUnicodeTables(); } /* * NAME - LoadFuncs *
* DESCRIPTION * This function loads the nwsso.dll and gets the function references. * */ static int LoadFuncs(void) { HINSTANCE dllHandle = LoadLibrary("nwsso.dll"); if(dllHandle == NULL) { printf( "Couldn't find DLL\n" ); return(FALSE); } // loading all of the new APIs p_NSSOAddSecretID = (NSSOADDSECRETID_T)GetProcAddress(dllHandle, "NSSOAddSecretID"); p_NSSOWriteSecret = (NSSOWRITESECRET_T)GetProcAddress(dllHandle, "NSSOWriteSecret"); p_NSSOReadSecret = (NSSOREADSECRET_T)GetProcAddress(dllHandle, "NSSOReadSecret"); p_NSSORemoveSecretID = (NSSOREMOVESECRETID_T)GetProcAddress(dllHandle, "NSSORemoveSecretID"); p_NSSORemoveSecretStore = (NSSOREMOVESECRETSTORE_T)GetProcAddress(dllHandle, "NSSORemoveSecretStore"); p_NSSOEnumerateSecretIDs = (NSSOENUMERATESECRETIDS_T)GetProcAddress(dllHandle, "NSSOEnumerateSecretIDs"); p_NSSOUnlockSecrets = (NSSOUNLOCKSECRETS_T)GetProcAddress(dllHandle, "NSSOUnlockSecrets"); p_NSSOGetServiceInfo = (NSSOGETSERVICEINFO_T)GetProcAddress(dllHandle, "NSSOGetServiceInfo"); // loading all of the original APIs p_NWSSAddSecretID = (NWSSADDSECRETID_T)GetProcAddress(dllHandle, "NWSSAddSecretID"); p_NWSSWriteSecret = (NWSSWRITESECRET_T)GetProcAddress(dllHandle, "NWSSWriteSecret"); p_NWSSReadSecret = (NWSSREADSECRET_T)GetProcAddress(dllHandle, "NWSSReadSecret"); p_NWSSRemoveSecretID = (NWSSREMOVESECRETID_T)GetProcAddress(dllHandle, "NWSSRemoveSecretID"); p_NWSSRemoveSecretStore = (NWSSREMOVESECRETSTORE_T)GetProcAddress(dllHandle, "NWSSRemoveSecretStore"); p_NWSSEnumerateSecretIDs = (NWSSENUMERATESECRETIDS_T)GetProcAddress(dllHandle, "NWSSEnumerateSecretIDs"); p_NWSSUnlockSecrets = (NWSSUNLOCKSECRETS_T)GetProcAddress(dllHandle, "NWSSUnlockSecrets"); return((p_NSSOAddSecretID && p_NSSOWriteSecret && p_NSSOReadSecret && p_NSSORemoveSecretID && p_NSSORemoveSecretStore && p_NSSOEnumerateSecretIDs && p_NSSOUnlockSecrets && p_NSSOGetServiceInfo && p_NWSSAddSecretID &&
p_NWSSWriteSecret && p_NWSSReadSecret && p_NWSSRemoveSecretID && p_NWSSRemoveSecretStore && p_NWSSEnumerateSecretIDs && p_NWSSUnlockSecrets) ? TRUE : FALSE); } /* * NAME - main * * DESCRIPTION * This is the main routing of the program. * */ int main(void) { /* beginning of the call */ /* ########################## DECLARATIONS START HERE ######################### */ NWRCODE rcode; SS_SECRET_T secret= {0}; SS_SECRET_ID_T secretID = {0}; SS_SECRET_ID_T uniID = {0}; SS_SECRET_ID_T uniDN = {0}; SS_SECRET_T *secretIDBuf = NULL; SS_SECRET_ID_T uniSrchStr = {0}; SS_SECRET_T uniSecIDList = {0}; int i, count; char *nameStr = NULL; unsigned long cVer, sVer, cCrypto, sCrypto; SS_CONTEXT_T dsCtx = {NSSO_DS_CTX_F, context, NULL}; /* ############################## CODE STARTS HERE ############################ */ if(!LoadFuncs()) { exit(NSSO_E_SYSTEM_FAILURE); } secret.data = (char *)malloc(256); strcpy((char *)secret.data, PASSWORD ); secret.len = strlen(PASSWORD)+1; strcpy(secretID.id, "\\\\novell.com\\SSO Loader Test:ver 1.0"); secretID.len = strlen(secretID.id)+1; if(InitNDS()) { return(NSSO_E_SYSTEM_FAILURE); } secret.data = (char *)malloc(256); strcpy((char *)secret.data, PASSWORD ); secret.len = strlen(PASSWORD)+1; strcpy(secretID.id, "\\\\novell.com\\SSO Loader Test:ver 1.0"); secretID.len = strlen(secretID.id)+1;
if(InitNDS()) { return(NSSO_E_SYSTEM_FAILURE); } if(rcode = NWLocalToUnicode(uniHandle, (unsigned short *)uniID.id, sizeof(uniID.id), secretID.id, (unicode) NULL, (nuint *)&uniID.len))& { rcode = NSSO_E_UNICODE_OP_FAILURE; goto Exit; } uniID.len = unisize((unicode *)uniID.id); //* convert DN to unicode if(rcode = NWLocalToUnicode(uniHandle,(unsigned short *)uniDN.id, MAX_DN_CHARS, objDN, (unicode) NULL,(nuint *)&uniDN.len))& { rcode = NSSO_E_UNICODE_OP_FAILURE; goto Exit; } uniDN.len = unisize((unicode *)uniDN.id); if(rcode = p_NSSOGetServiceInfo(&cVer, &sVer, &cCrypto, &sCrypto, NULL))& { printf("\nError [%d] NSSOGetServiceInfo\n", rcode); goto Exit; } else { printf("\nClient Version = %x\n", cVer); printf("Server Version = %x\n", sVer); if(cCrypto == NSSO_NICI_DOMESTIC_ENGINE) { printf("Client Crypto Strength = DOMESTIC\n"); } else if(cCrypto == NSSO_NICI_EXPORT_ENGINE) { printf("Client Crypto Strength = EXPORT\n"); } else { printf("Client Crypto Strength = UNDETERMINED\n"); } if(sCrypto == NSSO_NICI_DOMESTIC_ENGINE) { printf("Server Crypto Strength = DOMESTIC\n"); } else if(sCrypto == NSSO_NICI_EXPORT_ENGINE) { printf("Server Crypto Strength = EXPORT\n"); } else { printf("Server Crypto Strength = UNDETERMINED\n"); } }
printf("Creating secret ID [%s] in SS\n", secretID.id); rcode = p_NSSOAddSecretID(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F, &uniID, NULL);& if (rcode) { printf("Error [%d] NSSOAddSecretID...\n", rcode); goto Exit; } printf("Added secretID\n"); rcode = p_NSSOWriteSecret(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F|& NSSO_ENHANCED_PROTECTION_F, &uniID, &secret, NULL);& if(rcode) { printf("Error [%d] NSSOWriteSecret\n", rcode); goto Exit; } printf("Wrote secret [%s] len [%d]\n", secret.data, secret.len); // zero out secret memset(secret.data, 0, secret.len); rcode = p_NSSOReadSecret(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F, &uniID, &secret, NULL);& if(rcode) { printf("Error [%d] NSSOReadSecret\n", rcode); goto Exit; } printf("Read secret [%s] len [%d]\n", secret.data, secret.len); /* allocate and initialize the secretIDBuf */ if(!(secretIDBuf = (SS_SECRET_T *)malloc(NSSO_ENUM_BUFFER_GUESS + sizeof(SS_SECRET_T)))) { printf("Error: secreIDBuf MALLOC FAILED!\n"); goto Exit; } secretIDBuf->data = (nuint8 *)(secretIDBuf + sizeof(SS_SECRET_T)); if (!(uniSecIDList.data = (char *)malloc(NSSO_ENUM_BUFFER_GUESS + sizeof(SS_SECRET_T)))) { printf("Error: uniSecIDBuf MALLOC FAILED!\n"); goto Exit; } /* enumerate the secrets */ count = 0; uniSecIDList.len = secretIDBuf->len = NSSO_ENUM_BUFFER_GUESS; rcode = p_NSSOEnumerateSecretIDs(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F, & uniSrchStr.id, &count, &uniSecIDList, NULL);&
if(rcode) { printf("Error [%d] NSSOEnumerateSecretIDs\n", rcode); goto Exit; } /* convert the list back from unicode to print */ if(rcode = NWUnicodeToLocal(uniHandle, secretIDBuf->data, secretIDBuf->len, (punicode)uniSecIDList.data, (nuint8)NULL, (pnuint)&secretIDBuf->len))& { printf("Error [%d] NWUnicodeToLocal Failed\n", rcode); goto Exit; } printf("Number of Secrets = [%d]\nRaw Secret ID Buffer from SS [%s]\n", count, (char*)secretIDBuf->data); nameStr = strtok((char *)&secretIDBuf->data[0], "*");& for(i = 0; i < count; i++) { strcpy(secretID.id, nameStr); secretID.len = strlen(secretID.id)+1; printf("Extracted SecretID = [%s], len = [%d]\n", secretID.id, secretID.len); nameStr = strtok(NULL, "*"); } rcode = p_NSSORemoveSecretID(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F, &uniID, NULL);& if(rcode) { printf("Error [%d] NSSORemoveecretID\n", rcode); } printf("Removed secret...\n");
/* ########################## CODE EXITS HERE ##################### */ Exit: if(secret.data) free(secret.data); if(secretIDBuf) free(secretIDBuf); if(uniSecIDList.data) free(uniSecIDList.data); printf("hit a key...\n"); getch(); rcode = p_NSSORemoveSecretStore(&dsCtx, uniDN.id, NSSO_ALL_STRINGS_UNICODE_F, NULL);& DeInitNDS(); exit(rcode); /* ########################## CODE ENDS HERE ##################### */
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.