Repository: privacyidea/privacyidea

Issue:
Error 500 when validating a HOTP token without a PIN
### Top-level intent

What did you try to achieve?
Validate a HOTP token without a PIN.

### Steps to reproduce

1. Within the WEBUI, enroll a new HOTP token without a PIN.
2. Validate the HOTP token through the /validate/check endpoint.
3. Actual response:
```
{"detail": null, "id": 1, "jsonrpc": "2.0", "result": {"error": {"code": -500, "message": "500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application."}, "status": false}, "time": 1590439088.7281954, "version": "privacyIDEA 3.3.1", "signature": "rsa_sha256_pss:651f9f22ed62322d44e861d09325bf83aaf1c3b36568bd3e1dcea270da32dc701764462086e4e20fe7c823a3534161a035554fc5e473a20223d1972ec1a33a1f80872b048a951016813a17c836ec1217dff61425c821e1f962659887bd67c3d4ac10727e554e8763b3a242e109faaa8660672fef3be6027c3268ab9da61ab989da1b5219c6f456b3eed2aa8e94ee64e9be2f387118e7f0a1456ab6f5a7203bc047cf9ae9ff67d85a7d3bc586f7b3554cb0bfd3d8c1e592f55892facfb32d137dcd3127f9133725ccc128639ae40b14b949cc982cf29e755dbd551def418124d74ac43905ebe770d00dcdb6597056849b1fcfc7063f5eed680a2a146d08927c4d"}
```

### Expected outcome

What do you think, how the system should have worked?
It should have validated the token with a response like:
```
{"detail": {"message": "matching 1 tokens", "otplen": 6, "serial": "OATH00754647", "threadid": 140556219550336, "type": "hotp"}, "id": 1, "jsonrpc": "2.0", "result": {"status": true, "value": true}, "time": 1590439287.5389853, "version": "privacyIDEA 3.3.1", "versionnumber": "3.3.1", "signature": "rsa_sha256_pss:845ea1b2dcd882e61e3232d1f495edf1e04ee4509d2eea542d317904448ae9c1b64a24124d656948e7ff2938d36fd279f7b410a17dd97cbe29d300b87999afdc41fb893c065c2d003e42a8d6383a8a4729ca634cec37f648e77544520e214ea4c20725b4b40f82eaadadafa9985fac3318f4629d68c5f61f97c8ea123f996a457140fecce9e128e101dc47e74a2500ea647dc97451753564f36ed9c4435f1be413b1643d7747b611fdc292c68ea0b564228bb55c261dd5657fb7869cd8911cd667b800a51cde58f300995ab5d40f1ad0317cdf01e3ccba7128d6887a3633a8b34482dd55af2506cc21eabdda6031409fd1c917295d5228c04d9b1f0753f6707b"}
```

### Actual outcome

What did actually happen?
It answers with an HTTP 500 status code.

### Configuration

* **privacyIDEA version**: 3.3.1
* **Installation method**: github, PyPI, RHEL package dependencies
* **Python version**: 3.6.9
* **Operating system**: RHEL 7.8
* **Webserver**: NGINX Unit 1.17.0
* **Token database**: Oracle 19c (using SQLAlchemy cx_oracle dialect)

### Log file

**Set PI_LOGLEVEL = logging.DEBUG in pi.cfg and take a look at the privacyidea.log!**
**If appropriate, attach the log file or paste relevant portions.**

Attached logfile.
[privacyidea.log](https://github.com/privacyidea/privacyidea/files/4678847/privacyidea.log)




Discussion:
Thank you for filing an issue and sharing your observations or ideas. Please be sure to provide as many information as possible to help us working on this issue.
We can not reproduce this problem and never saw this before. In regards to your PR it looks like as if the ``userObject.pin`` is badly initialized.

Can you tell, which browser you are using?
Hi Cornelius!

We tried using PostgreSQL and it works fine. The problem only seems to occur when using Oracle as the database.

My browser is Chrome 83.0.4103.61 (32 bits build).
Thx! That is really interesting. So I know that Oracle sometimes is strangely picky about data types. It looks like, when no PIN is specified in the WebUI then *none*/NULL  would be passed to privacyIDEA so every other database would store this as an empty string. Only Oracle...
Actually I would prefer to check it when reading the pin from the db. Otherwise if we add an empty pin (i.e. `""` leads to `pin_hash` and `pin_seed` inserted into the db) we could get a number of side effects in the code.
If we check what Oracle returns as an _empty_ entry, we can adjust that part.
Unfortuantely I just cant get the Oracle test db to work... of course there must be a reason for so many high-paid consultants...

Resolving patch:
diff --git a/privacyidea/models.py b/privacyidea/models.py
--- a/privacyidea/models.py
+++ b/privacyidea/models.py
@@ -424,7 +424,7 @@ def check_pin(self, pin):
                     mypHash = self.get_hashed_pin(pin)
                 else:
                     mypHash = pin
-                if (mypHash == self.pin_hash):
+                if (mypHash == (self.pin_hash or u"")):
                     res = True
     
         return res
@@ -449,7 +449,7 @@ def check_pin(self, pin):
     def is_pin_encrypted(self, pin=None):
         ret = False
         if pin is None:
-            pin = self.pin_hash
+            pin = self.pin_hash or u""
         if pin.startswith("@@"):
             ret = True
         return ret


Test patch: