Adding authenticated attributes using MS CryptoApi - signing

I'm struggling adding authenticated attributes (OCSP data) to my message using CryptoApi. I first used CryptoApi's simplified message functions, but now switch to the low-level message functions, thinking that I would be able to control the message structure better. But I am once again stuck. My process is as follows:
Initialize CMSG_SIGNER_ENCODE_INFO and CMSG_SIGNED_ENCODE_INFO structure
I create a CRYPT_ATTRIBUTE for the ocsp date and specifies it in the CMSG_SIGNER_ENCODE_INFO structure
I then call CryptMsgCalculateEncodedLength to get the size
CryptMsgOpenToEncode with CMSG_SIGNED as the message type
CryptMsgUpdate, to insert my content into the message
CryptMsgGetParam with CMSG_CONTENT_PARAM to get the encoded blob
CryptMsgClose, I'm done with the message for now.
I open the message again to get the CMSG_ENCRYPTED_DIGEST, which is sent to a TSA and the result is added as an unaunthenticated attribute using CryptMsgControl.
I'm using this to sign signature tags in Adobe. So when there is no authenticated attributes, I receive three green check from Adobe:
The document has not been modified...
The document is signed by the current user
The signature includes an embedded timestamp (and the timestamp is validate)
But as soon as the authenticated attribute is added the signer's identity is invalidated and the timestamp data in incorrect. The CMSG_COMPUTED_HASH_PARAM when authenticated attributes are added and when not, differs. Should this not be the same? Since the document digest is of the content of the document and not of the authenticated attribute.
Is there another way to add authenticated attributes? I've tried to add it as a signer using CryptMsgControl, but that did not help either...

how about this step on adding the authenticated attributes for signing, example time stamping,
CryptEncodeObject(PKCS_7_ASN_ENCODING, szOID_RSA_signingTime, &curtime, pTime, &szTime);
pTime = (BYTE *)LocalAlloc(GPTR, szTime);
CryptEncodeObject(PKCS_7_ASN_ENCODING, szOID_RSA_signingTime, &curtime, pTime, &szTime);
time_blob.cbData = szTime;
time_blob.pbData = pTime;
attrib[0].pszObjId = szOID_RSA_signingTime;
attrib[0].cValue = 1;
attrib[0].rgValue = &time_blob;
CosignerInfo.cAuthAttr = 1;
CosignerInfo.rgAuthAttr = attrib;
and that Cosigner params is from CMSG_SIGNER_ENCODE_INFO CosignerInfo;

Related

How do I get the documentID in Business Objects Restful API?

I'm trying to figure out how to download a PDF from the BOE restful API.
I've been following the answer from ƘɌỈSƬƠƑ here:
SAP BI Open Doc URL for retrieving pdf
I was able to accomplish step 1 (getting the token).
But on the second step, it mentions using the documentID.
e.g.
/biprws/raylight/v1/documents/5690743/parameters
On the front end of BOE, if I click on the report, and choose Properties, it shows me that the "ID/CUID" is:
ID, CUID:746001, AdgNq_GsaqhOqnzc4gRN_Jg
Does that mean the "DocumentID" is 746001?
I'm not sure if I'm using the correct ID, because when I hit:
/biprws/raylight/v1/documents/746001/parameters
I get:
<error>
<error_code>100</error_code>
<message>Rule not respected (Argument 'reportIds' must not be null)</message>
</error>
You don't need to obtain prompt information (/parameters endpoint).
I think you are using the correct ID since the error is on the report. You obtain a 404 Not Found response status, if the document does not exist.
After a successful login, simply call /biprws/raylight/v1/documents/5690743 and add to your request an header with name Accept and value application/pdf. Of course the X-SAP-LogonToken should also be provided.
It will export the whole document. If you only need a specific report, you need to retrieve its ID first. Call the URI /biprws/raylight/v1/documents/5690743/reports with Accept header equals to application/json.
Choose one of the report, and get its ID (for example, in my case reportID equals 1234). Then you can export the report as a PDF by calling the URI: /biprws/raylight/v1/documents/5690743/reports/1234 with Accept header equals to application/pdf.

WSO2 Send Recovery Notification

In our current WSO2 setup, after a user performs a self creation, we place his account into a locked state, and send a confirmation email to the address specified during creation. This email has a link which allows the user to verify his account.
For development purposes, we are attempting to get the workflow down using the UserInformationRecoveryService wsdl in SOAP UI. The service which we seem to want is called sendRecoveryNotification. Here is the signature of this service:
sendRecoveryNotification(String username, String key, String notificationType)
The username parameter is simply the username of the WSO2 user in question, which we have. For the notificationType we have been using email, which presumably would trigger an email to be sent to the user. The problem is with the key parameter. It is not clear what value should be used as key, and all our guesses always lead to this error response:
18001 invalid confirmation code for user : tbiegeleisen#abc.com#tenant.com
We also noticed that several other services also expect a key, and it is not clear how to get this value.
Can someone shed light on the workflow for user recovery in WSO2? It seems to be a Catch-22 with regard of requiring a token in order to generate a new token to be sent to a user.
The WSO2 documentation clearly spells out the workflow for recovery with notification. The key which needs to be used is the return value from a call to the verifyUser() SOAP web service. This service itself expects a Captcha which normally would be sent from the UI. Here is a code snippet showing how a recovery notification can be sent:
String cookies = client.login("admin#tenant.com#tenant.com", "admin");
UserInformationRecoveryUtil userInfoutil = new UserInformationRecoveryUtil(webserviceUrl, cookies);
CaptchaInfoBean captchaInfo = new CaptchaInfoBean();
captchaInfo.setImagePath(captchaPath);
captchaInfo.setSecretKey(captchaKey);
captchaInfo.setUserAnswer(captcha);
String username = emailId + "#" + tenantDomain;
String key = userInfoutil.verifyUser(username, captchaInfo);
// now pass the key based on the Captcha along with the type of recovery action
userInfoutil.sendRecoveryNotification(username, key, "accountUnLock");

Webapplication log in system

I am using revel to build my webapplication and trying to write authentication module.
I finished with sign up part and now heading to write sign in part.
I read about security part on The definitive guide to form-based website authentication and will use this recommendation.
What I am really do not know is, how sign in works. I am imaging that the process works like this:
User write username and password into the html form and press sign in
Server receive request and the controller will check, if user information match with data on database.
If yes, how continue.
The third point is where I am staying. But I have some idea how could works and not sure, if is the right way.
So when sign in information match with the database, I would set in session object(hash datatype) key value pair signed_in: true. Everytime when the user make a request to the webapplication, that need to be authenticated, I would look in the session object, if signed_in is true or not.
This is the way I would do, but as I mentioned above, I do not know if it is the right way.
Yes like #twotwotwo mentioned, give it the user id and also a role.
So server side rendered flow: Step 1
user sends username (or other identifier) and secret.
using scrypt or bcrypt the secret is checked against the stored salted hash in the database
if it matches you create a struct or a map
serialize struct or map into string (json, msgpack, gob)
encrypt the string with AES https://github.com/gomango/utility/blob/master/crypto.go (for instance). Set a global AES key.
create a unique cookie (or session) identifier (key)
store identifier and raw struct or map in database
send encrypted cookie out (id = encrypted_struct_or_map aka the encrypted string)
On a protected resource (or page): Step 2
read identifier from cookie
check if id exists in db
decode cookie value using AES key
compare values from cookie with stored values
if user.role == "allowed_to_access_this_resource" render page
otherwise http.ResponseWriter.WriteHeader(403) or redirect to login page
Now if you wanted you could also have an application-wide rsa key and before encrypting the cookie value sign the string with the rsa private key (in Step 1). In Step 2 decode with AES key, check if signature valid, then compare content to db stored content.
On any changes you have to update the cookie values (struct/map) and the info in the database.

make OCSP response unique

I sign document with PADES LTV Profile. Signer library is written base on Pdfbox library.
I have one problem.
In PADES LTV profile, the final revision must be checked in online (It means that OCSP responses, CRLS and certificates of this revision must not be in document secure store (DSS)).
For testing, I add 12 revision to my document.
Every time when I add new revision, I do not add certificates and ocsp responses of this current revision to the DSS. I add previous revisions certificates and ocsp responses to the DSS. I do this because last revision must be checked in online. So I must not add OCSP response of last revision to the DSS. I do so, but sometimes Adobe reader thinks that last revision have embedded OCSP response in the document.
The problem might be is that following:
Each ocsp response must be unique, even if when we generate them with the same certificate. In the other words, If we request ocsp object twice, they must be unique.
For this I do that following but it does not work:
private OCSPReq buildOcspRequest(X509Certificate issuerCert, BigInteger serialNumber, File inputDocument) {
InputStream is = new FileInputStream(inputDocument);
X509CertificateHolder certificateHolder;
certificateHolder = new X509CertificateHolder(issuerCert.getEncoded());
CertificateID id = new CertificateID(new BcDigestCalculatorProvider().get(CertificateID.HASH_SHA1), certificateHolder, serialNumber);
OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
ocspReqBuilder.addRequest(id);
DigestCalculatorProvider digestCalculatorProvider;
JcaDigestCalculatorProviderBuilder digestCalcProvBuilder = new JcaDigestCalculatorProviderBuilder().setProvider("BC");
digestCalculatorProvider = digestCalcProvBuilder.build();
// get SHA 256
DigestCalculator digest = digestCalculatorProvider.get(AlgorithmIdentifier.getInstance("2.16.840.1.101.3.4.2.1"));
OutputStream os = digest.getOutputStream();
IOUtils.copy(is, os);
byte[] messageImprint = digest.getDigest();
BigInteger time = BigInteger.valueOf(System.currentTimeMillis());
// time + imprint
byte[] nonce = ArrayUtils.addAll(time.toByteArray(), messageImprint);
Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonce);
ocspReqBuilder.setRequestExtensions(new Extensions(extension));
return ocspReqBuilder.build();
}
this is testing pdf link SAMPLE PDF
I might create 4 revision and everything might be all right ... I don't know , sometimes it happens... When I was testing, the problem occours when I create many revisions... THE LAST REVISION THINKS THAT OCSP RESPONSE OF PREVIOUS REVISIONS IS IT'S OWN!
In PADES LTV profile, the final revision must be checked in online
No.
PAdES, i.e. ETSI TS 102 778, in part 4 (PAdES-LTV Profile) merely recommends this:
4.3 Validation Process
It is recommended that that validation process be as follows:
1) The "latest" document Time-stamp should be validated at current time with validation data collected at the current time.
The word should indicates a recommendation, and the sentence before actually spells it out.
But let's assume you want to follow the recommendation. Your interpretation
(It means that OCSP responses, CRLS and certificates of this revision must not be in document secure store (DSS)).
is not correct still: There may be validation related information (OCSP responses, CRLs, certificates) in the document which (seen as isolated information) apply to the outer time stamp or signature. If you time stamp your document twice in short succession using the same time stamp service and add a CRL for certificates used in the first time stamp in the time between, chances are that the outer time stamp involves certificates covered by this CRL and is applied in the validity interval indicated by the CRL.
No, it is the responsibility of the verifier not to use these information if the verifier chose to follow the PAdES-LTV recommendation quoted above.
Adobe Reader does not claim to follow this recommendation (at least as far as I know). Thus, if you verify the signatures and time stamps using Adobe Reader, information contained in the document may be used to verify the outer time stamp, too.
Actually Adobe originally loved the concept of first retrieving validation related information and signing and time stamping everything including those information thereafter.
The problem might be is that following:
Each ocsp response must be unique, even if when we generate them with the same certificate. In the other words, If we request ocsp object twice, they must be unique.
No. While it is good style to use nonces, your observation has nothing to do with them.
The reason why Adobe Reader sometimes (and only sometimes) makes use of already embedded information for verifying outer signatures / time stamps is that OCSP responses and CRLs have validity intervals defined by their thisUpdate and nextUpdate fields which sometimes (if you add multiple time stamps by the same TSA) in spite of being embedded for the validation of an older time stamp still encompass the time of the newly added one (and, thus, are also used for their validation).
If you want to prevent this, you have to check the OCSP responses and CRLs already contained in the PDF or just now added to it by you, inspect those whose respective validity interval has not yet ended, and not apply any time stamp to the document whose certificates can be validated with them.

Freeradius users operators

I faced with one issue, which I can't understand in Freeradius users file.
My goal is just authenticate external user "shad" with password "test".
I added line in /etc/raddb/users the following line:
shad Cleartext-Password == "test"
Result was Reject. If I change "==" operator to ":=" Authentication is successful.
So my question is the following:
Why I can't use "==" operator while FreeRadius documentation tells:
"Attribute == Value
As a check item, it matches if the named attribute is present in the request, AND has the given value."
And one more question.
In some resourses I faced with such lines:
shad Auth-Type := Local, User-Password == "test"
I tried and it doesn't work. Responce is Reject with log:
[pap] WARNING! No "known good" password found for the user. Authentication may fail because of this.
How the users file works
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.
There are three lists of attribute(s) (pairs) that are accessible from the users file. These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.
request - Contains all the pairs from the original request received from the NAS (Network Access Server) via the network.
control - Initially contains no pairs, but is populated with pairs that control how modules process the current request. This is done from the users file or unlang (the FreeRADIUS policy language used in virtual servers).
reply - Contains pairs you want to send back to the NAS via the network.
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.
check and control pairs are distinguished by the operator used. If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair. If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.
Cleartext-Password
Cleartext-Password is strictly a control pair. It should not be present in any of the other lists.
Cleartext-Password is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is SSHA-Password - this contains a salted SHA hash of the users password.
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the 'User-Password' pair. In this case that module is 'rlm_pap'.
User-Password
User-Password is strictly a request pair. It should not be present in any of the other lists.
User-Password is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS. In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like Cleartext-Password.
In a users file entry when setting reference passwords you'll see entries like:
my_username Cleartext-Password := "known_good_password"
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".
To answer the first question the reason why:
shad Cleartext-Password == "test"
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.
Auth-Type
Auth-Type is strictly a control pair. It should not be present in any of the other lists.
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.
authorize is the information gathering section. This is where database lookups are done to authorise the user, and to retrieve reference passwords. It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.
Authenticate is where a specific module is called to perform authentication. The module is determined by Auth-Type.
Post-Auth is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.
If no Auth-Type is set the request will be rejected.
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.
There's also a 'magic' Auth-Type, 'Accept', which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:
shad Auth-Type := Accept, User-Password == "test"